Trees and Binary Search Trees
Trees organise data hierarchically. This chapter introduces tree terminology, binary-tree representations, recursive and iterative traversals, breadth-first search, common binary-tree problems, and binary search tree construction.
8.1What is a Tree?
8.2Tree Terminology
The topmost node in a tree.
A connection between two nodes.
A node derived from a parent.
A node with one or more children.
A node with no children.
8.3Types of Trees
Each node has at most two children: zero, one, or two.
Node 1 has three children, so the binary-tree rule is violated.
Every node has either zero or two children.
Every level is full except possibly the last, which fills from left to right.
A self-balancing BST.
A tree with a maximum or minimum property.
A balanced tree designed for disk storage.
8.4Binary Tree Representation
Array representation
For a node at index i:
- left child =
2i + 1 - right child =
2i + 2 - parent =
⌊(i − 1) / 2⌋, fori > 0
Linked representation
Each node stores data plus pointers to its left and right children.
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class Tree:
def __init__(self):
self.root = None
8.5Binary Tree Traversals
| Traversal | Order | Lecture sequence |
|---|---|---|
| Inorder | Left, Root, Right | 4 → 2 → 5 → 1 → 6 → 3 → 7 |
| Preorder | Root, Left, Right | 1 → 2 → 4 → 5 → 3 → 6 → 7 |
| Postorder | Left, Right, Root | 4 → 5 → 2 → 6 → 7 → 3 → 1 |
Program call stack
8.6Recursive Traversals
Inorder
InorderTraversal(node):
if node is not NULL:
InorderTraversal(node.left)
Visit(node)
InorderTraversal(node.right)
Preorder
PreorderTraversal(node):
if node is not NULL:
Visit(node)
PreorderTraversal(node.left)
PreorderTraversal(node.right)
Postorder
PostorderTraversal(node):
if node is not NULL:
PostorderTraversal(node.left)
PostorderTraversal(node.right)
Visit(node)
8.7Iterative Traversals with Stacks
Explicit stack S
Explicit stack S2
show the iterative algorithms
Iterative inorder
IterativeInorderTraversal(root):
Initialize an empty stack
current = root
while current is not NULL or stack is not empty:
while current is not NULL:
Push current to stack
current = current.left
current = Pop from stack
Visit(current)
current = current.right
Iterative preorder using one stack
IterativePreorder(root):
if root == NULL: return
Push root into stack S
while S is not empty:
node = S.pop()
Visit(node)
if node.right != NULL: Push node.right
if node.left != NULL: Push node.left
Iterative postorder using two stacks
IterativePostorder(root):
if root == NULL: return
Push root into S1
while S1 is not empty:
node = S1.pop()
Push node into S2
if node.left != NULL: Push node.left into S1
if node.right != NULL: Push node.right into S1
while S2 is not empty:
Visit(S2.pop())
8.8Level-Order Traversal — BFS
LEVEL-ORDER(root): 1. Initialize an empty queue 2. Enqueue the root node 3. Repeat until the queue is empty: a. Dequeue a node and process it b. Enqueue its left child, if it exists c. Enqueue its right child, if it exists
Queue · front to rear
Output
8.9Problems on Binary Trees
Count the number of nodes.
Find a given key.
Find the smallest and largest values.
Process children before their parent.
Find the longest root-to-leaf path.
Find the node at maximum depth.
Compare two binary-tree shapes.
Add every element in the tree.
Height(root): 1. if root == NULL: return 0 2. left_height = Height(root.left) 3. right_height = Height(root.right) 4. return 1 + max(left_height, right_height)
SumTree(root): 1. if root == NULL: return 0 2. left_sum = SumTree(root.left) 3. right_sum = SumTree(root.right) 4. return root.data + left_sum + right_sum
8.10Reconstructing a Tree from Traversals
D B E A F C
A B D E C F
8.11Binary Search Tree — Searching
SEARCH(root, key):
1. if root == NULL: return NULL
2. if root.data == key: return root
3. if key < root.data:
return SEARCH(root.left, key)
4. return SEARCH(root.right, key)
8.12BST Construction
Insert(node, key):
1. if node is NULL:
return a new node containing key
2. if key < node.data:
node.left = Insert(node.left, key)
3. else if key > node.data:
node.right = Insert(node.right, key)
4. return node
show balanced construction from a sorted array
build_tree(arr):
if not arr: return None
mid = len(arr) // 2
node = Node(arr[mid])
node.left = build_tree(arr[:mid])
node.right = build_tree(arr[mid + 1:])
return node
8.13Questions and Self Study
show answer
O(1) The root has no left child, so it is already the minimum.
show answer
O(n) Follow the left pointer through every node.