Binary Tree
A Binary Tree is one of the most important and widely used data structures in computer science. It consists of nodes, each with a maximum of two children, referred to as the left child and the right child. Binary trees are used in various applications such as expression evaluation, searching, and sorting.
In this blog post, we will explore the structure of binary trees, the different types of binary trees, and common operations that can be performed on them. Additionally, we will include some Python code examples to help solidify your understanding.
A Binary Tree is a hierarchical data structure consisting of nodes, where each node has at most two child nodes—commonly referred to as the left and right children. The structure of a binary tree is often depicted visually as a tree with a root node and a branching pattern of nodes connected by edges.
The height of a binary tree is defined as the number of edges on the longest path from the root to any leaf. For an empty tree, the height is -1, and for a tree with just one node, the height is 0.
There are several types of binary trees, each with unique properties suited for different applications.
A full binary tree is a binary tree in which every node has either 0 or 2 children. This means that no node can have just one child.
A complete binary tree is a binary tree where all the levels, except possibly the last, are fully filled, and all the nodes are as far left as possible. This type of tree is used in heap-based data structures like heaps and priority queues.
A perfect binary tree is one in which all the internal nodes have exactly two children, and all the leaf nodes are at the same level.
A balanced binary tree is one in which the height of the two subtrees of every node differ by at most one. The AVL tree is an example of a balanced binary tree.
A degenerate binary tree is a tree where every parent node has only one child. This effectively makes the tree behave like a linked list.
Several basic operations can be performed on binary trees, including insertion, deletion, searching, and traversal.
Insertion in a binary tree typically involves placing a new node at the first available position (in level order), ensuring the tree remains complete or balanced.
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.value = key
def insert(root, key):
new_node = Node(key)
if root is None:
root = new_node
return root
queue = []
queue.append(root)
while queue:
temp = queue.pop(0)
if not temp.left:
temp.left = new_node
return root
else:
queue.append(temp.left)
if not temp.right:
temp.right = new_node
return root
else:
queue.append(temp.right)
# Example of Binary Tree Insertion
root = Node(1)
root = insert(root, 2)
root = insert(root, 3)
root = insert(root, 4)
root = insert(root, 5)
Deletion in a binary tree is a bit more involved than insertion, as it requires finding the node to delete and then re-arranging the tree to maintain its structure. In the case of binary search trees (BST), deletion also involves ensuring that the binary search tree property is maintained.
Searching in a binary tree involves traversing through the nodes of the tree, starting from the root and visiting each node in a specific order (depending on the type of traversal).
Traversal refers to visiting all the nodes in a specific order. The primary types of tree traversal are:
We will discuss Binary Tree Traversal methods in another dedicated post, but here’s a brief overview of traversal orders:
Here’s how to implement inorder traversal for a binary tree in Python:
def inorder_traversal(root):
if root:
inorder_traversal(root.left) # Visit left subtree
print(root.value, end=" ") # Visit root
inorder_traversal(root.right) # Visit right subtree
# Perform Inorder Traversal
print("Inorder Traversal:")
inorder_traversal(root)
Inorder Traversal:
4 2 5 1 3