Binary Tree is a non-linear and hierarchical data structure where each node has at most two children referred to as the left child and the right child. The topmost node in a binary tree is called the root, and the bottom-most nodes are called leaves.
Introduction to Binary TreeRepresentation of Binary Tree
Each node in a Binary Tree has three parts:
- Data
- Pointer to the left child
- Pointer to the right child
Binary Tree Representation Create/Declare a Node of a Binary Tree in Python
Syntax to declare a Node of Binary Tree in Python:
Python
# A Python class that represents
# an individual node in a Binary Tree
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key
Example for Creating a Binary Tree in Python
Here’s an example of creating a Binary Tree with four nodes (2, 3, 4, 5)
Creating a Binary Tree having three nodes
Python
class Node:
def __init__(self, d):
self.data = d
self.left = None
self.right = None
# Initialize and allocate memory for tree nodes
firstNode = Node(2)
secondNode = Node(3)
thirdNode = Node(4)
fourthNode = Node(5)
# Connect binary tree nodes
firstNode.left = secondNode
firstNode.right = thirdNode
secondNode.left = fourthNode
In the above code, we have created four tree nodes firstNode, secondNode, thirdNode and fourthNode having values 2, 3, 4 and 5 respectively.
- After creating three nodes, we have connected these node to form the tree structure like mentioned in above image.
- link secondNode to the left child of firstNode by firstNode.left = secondNode.
- link thirdNode to the right child of firstNode by firstNode.right = thirdNode.
- link fourthNode to the left child of secondNode by secondNode.left = fourthNode.
Types of Binary Tree
Binary Tree can be classified into multiples types based on multiple factors:
- On the basis of Number of Children
- On the basis of Completion of Levels
- On the basis of Node Values:
read more about - Terminologies and properties of Binary Tree
Operations On Binary Tree
Following is a list of common operations that can be performed on a binary tree:
1. Traversal in Binary Tree
Traversal in Binary Tree involves visiting all the nodes of the binary tree. Tree Traversal algorithms can be classified broadly into two categories, DFS and BFS:
Depth-First Search (DFS) algorithms: DFS explores as far down a branch as possible before backtracking. It is implemented using recursion. The main traversal methods in DFS for binary trees are:
- Preorder Traversal (current-left-right): Visits the node first, then left subtree, then right subtree.
- Inorder Traversal (left-current-right): Visits left subtree, then the node, then the right subtree.
- Postorder Traversal (left-right-current): Visits left subtree, then right subtree, then the node.
Breadth-First Search (BFS) algorithms: BFS explores all nodes at the present depth before moving on to nodes at the next depth level. It is typically implemented using a queue. BFS in a binary tree is commonly referred to as Level Order Traversal.
Below is the implementation of traversals algorithm in binary tree:
Python
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
# In-order DFS: Left, Root, Right
def in_order_dfs(node):
if node is None:
return
in_order_dfs(node.left)
print(node.data, end=' ')
in_order_dfs(node.right)
# Pre-order DFS: Root, Left, Right
def pre_order_dfs(node):
if node is None:
return
print(node.data, end=' ')
pre_order_dfs(node.left)
pre_order_dfs(node.right)
# Post-order DFS: Left, Right, Root
def post_order_dfs(node):
if node is None:
return
post_order_dfs(node.left)
post_order_dfs(node.right)
print(node.data, end=' ')
# BFS: Level order traversal
def bfs(root):
if root is None:
return
queue = [root]
while queue:
node = queue.pop(0)
print(node.data, end=' ')
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if __name__ == "__main__":
# Creating the tree
root = Node(2)
root.left = Node(3)
root.right = Node(4)
root.left.left = Node(5)
print("In-order DFS: ", end='')
in_order_dfs(root)
print("\nPre-order DFS: ", end='')
pre_order_dfs(root)
print("\nPost-order DFS: ", end='')
post_order_dfs(root)
print("\nLevel order: ", end='')
bfs(root)
OutputIn-order DFS: 5 3 2 4
Pre-order DFS: 2 3 5 4
Post-order DFS: 5 3 4 2
Level order: 2 3 4 5
2. Insertion in Binary Tree
Inserting elements means add a new node into the binary tree. As we know that there is no such ordering of elements in the binary tree, So we do not have to worry about the ordering of node in the binary tree. We would first creates a root node in case of empty tree. Then subsequent insertions involve iteratively searching for an empty place at each level of the tree. When an empty left or right child is found then new node is inserted there. By convention, insertion always starts with the left child node.
Insertion in Binary Tree
Python
from collections import deque
class Node:
def __init__(self, d):
self.data = d
self.left = None
self.right = None
# Function to insert a new node in the binary tree
def insert(root, key):
if root is None:
return Node(key)
# Create a queue for level order traversal
queue = deque([root])
while queue:
temp = queue.popleft()
# If left child is empty, insert the new node here
if temp.left is None:
temp.left = Node(key)
break
else:
queue.append(temp.left)
# If right child is empty, insert the new node here
if temp.right is None:
temp.right = Node(key)
break
else:
queue.append(temp.right)
return root
# In-order traversal
def inorder(root):
if root is None:
return
inorder(root.left)
print(root.data, end=" ")
inorder(root.right)
if __name__ == "__main__":
root = Node(2)
root.left = Node(3)
root.right = Node(4)
root.left.left = Node(5)
print("Inorder traversal before insertion: ", end="")
inorder(root)
print()
key = 6
root = insert(root, key)
print("Inorder traversal after insertion: ", end="")
inorder(root)
print()
OutputInorder traversal before insertion: 5 3 2 4
Inorder traversal after insertion: 5 3 6 2 4
3. Searching in Binary Tree
Searching for a value in a binary tree means looking through the tree to find a node that has that value. Since binary trees do not have a specific order like binary search trees, we typically use any traversal method to search. The most common methods are depth-first search (DFS) and breadth-first search (BFS). In DFS, we start from the root and explore the depth nodes first. In BFS, we explore all the nodes at the present depth level before moving on to the nodes at the next level. We continue this process until we either find the node with the desired value or reach the end of the tree. If the tree is empty or the value isn’t found after exploring all possibilities, we conclude that the value does not exist in the tree.
Here is the implementation of searching in a binary tree using Depth-First Search (DFS):
Python
class Node:
def __init__(self, d):
self.data = d
self.left = None
self.right = None
# Function to search for a value in the binary tree using DFS
def searchDFS(root, value):
# Base case: If the tree is empty or we've reached a leaf node
if root is None:
return False
# If the node's data is equal to the value we are searching for
if root.data == value:
return True
# Recursively search in the left and right subtrees
left_res = searchDFS(root.left, value)
right_res = searchDFS(root.right, value)
return left_res or right_res
if __name__ == "__main__":
root = Node(2)
root.left = Node(3)
root.right = Node(4)
root.left.left = Node(5)
root.left.right = Node(6)
value = 6
if searchDFS(root, value):
print(f"{value} is found in the binary tree")
else:
print(f"{value} is not found in the binary tree")
Output6 is found in the binary tree
4. Deletion in Binary Tree
Deleting a node from a binary tree means removing a specific node while keeping the tree’s structure. First, we need to find the node that want to delete by traversing through the tree using any traversal method. Then replace the node’s value with the value of the last node in the tree (found by traversing to the rightmost leaf), and then delete that last node. This way, the tree structure won’t be effected. And remember to check for special cases, like trying to delete from an empty tree, to avoid any issues.
Note: There is no specific rule of deletion but we always make sure that during deletion the binary tree proper should be preserved.
Deletion in Binary Tree
Python
from collections import deque
class Node:
def __init__(self, d):
self.data = d
self.left = None
self.right = None
# Function to delete a node from the binary tree
def deleteNode(root, val):
if root is None:
return None
# Use a queue to perform BFS
queue = deque([root])
target = None
# Find the target node
while queue:
curr = queue.popleft()
if curr.data == val:
target = curr
break
if curr.left:
queue.append(curr.left)
if curr.right:
queue.append(curr.right)
if target is None:
return root
# Find the deepest rightmost node and its parent
last_node = None
last_parent = None
queue = deque([(root, None)])
while queue:
curr, parent = queue.popleft()
last_node = curr
last_parent = parent
if curr.left:
queue.append((curr.left, curr))
if curr.right:
queue.append((curr.right, curr))
# Replace target's value with the last node's value
target.data = last_node.data
# Remove the last node
if last_parent:
if last_parent.left == last_node:
last_parent.left = None
else:
last_parent.right = None
else:
return None
return root
# In-order traversal
def inorder(root):
if root is None:
return
inorder(root.left)
print(root.data, end=" ")
inorder(root.right)
if __name__ == "__main__":
root = Node(2)
root.left = Node(3)
root.right = Node(4)
root.left.left = Node(5)
root.left.right = Node(6)
print("Original tree (in-order): ", end="")
inorder(root)
print()
val_to_del = 3
root = deleteNode(root, val_to_del)
print(f"Tree after deleting {val_to_del} (in-order): ", end="")
inorder(root)
print()
OutputOriginal tree (in-order): 5 3 6 2 4
Tree after deleting 3 (in-order): 5 6 2 4
Auxiliary Operations On Binary Tree
Similar Reads
Binary Search Tree In Python
A Binary search tree is a binary tree where the values of the left sub-tree are less than the root node and the values of the right sub-tree are greater than the value of the root node. In this article, we will discuss the binary search tree in Python. What is a Binary Search Tree(BST)?A Binary Sear
11 min read
numpy.binary_repr() in Python
numpy.binary_repr(number, width=None) function is used to represent binary form of the input number as a string. For negative numbers, if width is not given, a minus sign is added to the front. If width is given, the twoâs complement of the number is returned, with respect to that width. In a twoâs-
3 min read
bin() in Python
Python bin() function returns the binary string of a given integer. bin() function is used to convert integer to binary string. In this article, we will learn more about Python bin() function. Example In this example, we are using the bin() function to convert integer to binary string. C/C++ Code x
2 min read
Binary Heap in Python
A Binary Heap is a complete Binary Tree that is used to store data efficiently to get the max or min element based on its structure. A Binary Heap is either a Min Heap or a Max Heap. In a Min Binary Heap, the key at the root must be minimum among all keys present in a Binary Heap. The same property
3 min read
Reading binary files in Python
Reading binary files means reading data that is stored in a binary format, which is not human-readable. Unlike text files, which store data as readable characters, binary files store data as raw bytes. Binary files store data as a sequence of bytes. Each byte can represent a wide range of values, fr
6 min read
Working with Binary Data in Python
Alright, lets get this out of the way! The basics are pretty standard: There are 8 bits in a byteBits either consist of a 0 or a 1A byte can be interpreted in different ways, like binary octal or hexadecimal Note: These are not character encodings, those come later. This is just a way to look at a s
5 min read
Binarytree Module in Python
A binary tree is a data structure in which every node or vertex has at most two children. In Python, a binary tree can be represented in different ways with different data structures(dictionary, list) and class representations for a node. However, binarytree library helps to directly implement a bin
6 min read
SymPy | Subset.next_binary() in Python
Subset.next_binary() : next_binary() is a sympy Python library function that returns the next binary ordered subset. Syntax : sympy.combinatorics.subset.Subset.next_binary() Return : the next binary ordered subset Code #1 : next_binary() Example # Python code explaining # SymPy.Subset.next_binary()
1 min read
numpy.base_repr() in Python
numpy.base_repr(number, base=2, padding=0) function is used to return a string representation of a number in the given base system. For example, decimal number 10 is represented as 1010 in binary whereas it is represented as 12 in octal. Syntax : numpy.base_repr(number, base=2, padding=0) Parameters
3 min read
SymPy | Subset.prev_binary() in Python
Subset.prev_binary() : prev_binary() is a sympy Python library function that returns the previous binary ordered subset. Syntax : sympy.combinatorics.subset.Subset.prev_binary() Return : the previous binary ordered subset. Code #1 : prev_binary() Example # Python code explaining # SymPy.Subset.prev_
1 min read