Key Takeaways: A Binary Tree is a specific type of Tree data structure. Its defining rule is simple: Every node can have a maximum of two children (Left and Right).
In the previous tutorial, we learned about standard Trees. A normal Tree node can have an infinite number of children.
However, the most famous and widely used tree in Computer Science is the Binary Tree. Let's break down exactly how it works.
The word "Binary" means two.
In a Binary Tree, a parent node is strictly limited to having:
0 children (This is called a Leaf node).1 child (Either Left or Right).2 children (Both Left and Right).A node can never have 3 or more children!
A Binary Tree: Each node splits into a maximum of two smaller paths.
Under the hood, a Binary Tree Node is very similar to a Doubly Linked List Node.
Instead of pointing "Forward" and "Backward", it points "Left" and "Right".
Every node must store three things:
10).Binary Trees come in a few different "shapes." Knowing these names is very helpful for technical interviews:
0 or 2 children. 2 children, and all Leaf nodes are on the exact same bottom level.With an Array, you just loop from index 0 to the end. But how do you "loop" through a Tree?
We use Depth-First Search (DFS) traversals. There are three standard ways to read the data in a Binary Tree:
Left -> Root -> RightRoot -> Left -> RightLeft -> Right -> RootFirst, we need to create our Node class and build the basic structure of the tree.
class Node: def __init__(self, data): self.left = None self.right = None self.data = data# Create the Root Node root = Node(10)
# Add Left and Right Children root.left = Node(5) root.right = Node(15)
# Add grandchildren root.left.left = Node(2) root.left.right = Node(7)
Now, let's write the code for the three different Depth-First Search traversals! Notice how we use Recursion (a function calling itself) to effortlessly walk down the left and right branches.
def inorder_traversal(node): # Base case: If the node is None, stop! if node is not None: # 1. Visit the Left child inorder_traversal(node.left) # 2. Print the Root (Current Node) print(node.data, end=" ") # 3. Visit the Right child inorder_traversal(node.right)print("In-Order Traversal:") inorder_traversal(root)
def preorder_traversal(node): if node is not None: # 1. Print the Root first print(node.data, end=" ") # 2. Visit the Left child preorder_traversal(node.left) # 3. Visit the Right child preorder_traversal(node.right)print("\nPre-Order Traversal:") preorder_traversal(root)
def postorder_traversal(node): if node is not None: # 1. Visit the Left child postorder_traversal(node.left) # 2. Visit the Right child postorder_traversal(node.right) # 3. Print the Root last print(node.data, end=" ")print("\nPost-Order Traversal:") postorder_traversal(root)
What is the strict rule for a node in a Binary Tree?
Which traversal order reads the Left child, then the Root, then the Right child?