C Data Structures: Binary Trees & Binary Search Trees (BST) Masterclass
Welcome to Phase 18 (Chapter 49): C Data Structures โ Binary Trees & Binary Search Trees (BST) Masterclass! A Binary Search Tree enforces the BST invariant: for every node, all left subtree values are smaller and all right subtree values are larger. This enables O(log n) search, insert, and delete in balanced trees.
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int data;
struct TreeNode *left, *right;
} TreeNode;
static TreeNode *new_node(int val) {
TreeNode *n = malloc(sizeof(TreeNode));
if (!n) { perror("malloc"); exit(1); }
n->data = val; n->left = n->right = NULL;
return n;
}
TreeNode *bst_insert(TreeNode *root, int val) {
if (!root) return new_node(val);
if (val < root->data) root->left = bst_insert(root->left, val);
else if (val > root->data) root->right = bst_insert(root->right, val);
/* val == root->data: ignore duplicates */
return root;
}
int bst_search(const TreeNode *root, int val) {
if (!root) return 0;
if (val == root->data) return 1;
return (val < root->data)
? bst_search(root->left, val)
: bst_search(root->right, val);
}
void inorder(const TreeNode *root) {
if (!root) return;
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
int height(const TreeNode *root) {
if (!root) return 0;
int l = height(root->left), r = height(root->right);
return 1 + (l > r ? l : r);
}
void free_tree(TreeNode *root) {
if (!root) return;
free_tree(root->left);
free_tree(root->right);
free(root);
}
int main(void) {
TreeNode *root = NULL;
int values[] = {50, 30, 70, 20, 40, 60, 80};
for (int i = 0; i < 7; i++) root = bst_insert(root, values[i]);
printf("In-order (sorted): "); inorder(root); printf("\n");
printf("Tree height: %d\n", height(root));
printf("Search 40: %s\n", bst_search(root, 40) ? "Found" : "Not Found");
printf("Search 99: %s\n", bst_search(root, 99) ? "Found" : "Not Found");
free_tree(root);
return 0;
}| Traversal | Order | Primary Use Case |
|---|---|---|
| In-order (LNR) | Left โ Node โ Right | Sorted output from BST. Database range queries. |
| Pre-order (NLR) | Node โ Left โ Right | Serialize / copy a tree. Expression tree evaluation. |
| Post-order (LRN) | Left โ Right โ Node | Safe tree deletion (children freed before parents). Evaluate postfix expressions. |
| Level-order (BFS) | Level by level, left-right | Shortest path. Print tree levels. Build min-heap. |
Q1: Why can BST become O(n) for search?
When inserting sorted data (1, 2, 3, 4, 5...) into a naive BST, the tree degenerates to a right-only linked list with O(n) search. Self-balancing trees (AVL, Red-Black) prevent this.
Q2: What is the BST delete algorithm?
Three cases: (1) Leaf โ simply free. (2) One child โ replace node with child. (3) Two children โ find in-order successor (smallest in right subtree), copy its value, delete the successor.
Q3: What is an AVL tree?
An AVL tree is a self-balancing BST where the height difference between left and right subtrees of every node (balance factor) never exceeds 1. Rotations (left, right, left-right, right-left) restore balance after insert/delete.
Q4: How do you implement level-order traversal?
Use a Queue. Enqueue root. Loop: dequeue node, print it, enqueue its non-null children. This processes nodes level by level, left to right.
Q5: What is the difference between a Binary Tree and a BST?
A Binary Tree is any tree where each node has at most 2 children. A BST is a Binary Tree that additionally enforces the ordering invariant (left < node < right) at every node.