Skip to main content
Advanced Data Structures
Advanced Data Structures
IOT
Rx 2h Lecture #2: Linked Lists

Binary Trees

Objectives

  • Understand tree terminology
  • Implement a binary search tree (BST)
  • Master the different traversal orders
  • Analyze the complexity of operations

Terminology

           50          <- Root
          /  \
        30    70       <- Internal nodes
       / \   / \
      20 40 60 80      <- Leaves
TermDefinition
RootNode with no parent (top of the tree)
LeafNode with no children
Internal nodeNode with at least one child
HeightMaximum distance from root to a leaf
DepthDistance from a node to the root
SubtreeTree formed by a node and its descendants

Binary Search Tree (BST)

A BST satisfies the property:

  • For every node N: values in the left subtree < N < values in the right subtree
Fundamental property

The inorder traversal of a BST yields the elements in sorted order!

Structure

typedef struct TreeNode {
    int data;
    struct TreeNode* left;
    struct TreeNode* right;
} TreeNode;

typedef TreeNode* Tree;

Basic Functions

// Is the tree empty?
int is_empty(Tree tree) {
    return tree == NULL;
}

// Is it a leaf?
int is_leaf(Tree tree) {
    return tree != NULL
        && tree->left == NULL
        && tree->right == NULL;
}

Insertion (recursive)

Tree insert(Tree tree, int value) {
    if (tree == NULL) {
        return create_node(value);
    }

    if (value < tree->data) {
        tree->left = insert(tree->left, value);
    } else if (value > tree->data) {
        tree->right = insert(tree->right, value);
    }
    // If equal, ignore (no duplicates)

    return tree;
}
int search(Tree tree, int value) {
    if (tree == NULL) {
        return 0;  // Not found
    }
    if (value == tree->data) {
        return 1;  // Found
    }
    if (value < tree->data) {
        return search(tree->left, value);
    }
    return search(tree->right, value);
}

Tree Traversals

Depth-First Search (DFS)

Preorder: Root - Left - Right

void preorder(Tree tree) {
    if (tree != NULL) {
        printf("%d ", tree->data);  // Root
        preorder(tree->left);        // Left
        preorder(tree->right);       // Right
    }
}

Inorder: Left - Root - Right

void inorder(Tree tree) {
    if (tree != NULL) {
        inorder(tree->left);         // Left
        printf("%d ", tree->data);   // Root
        inorder(tree->right);        // Right
    }
}

Postorder: Left - Right - Root

void postorder(Tree tree) {
    if (tree != NULL) {
        postorder(tree->left);       // Left
        postorder(tree->right);      // Right
        printf("%d ", tree->data);   // Root
    }
}

Traversal Example

           50
          /  \
        30    70
       / \   / \
      20 40 60 80
TraversalResult
Preorder50, 30, 20, 40, 70, 60, 80
Inorder20, 30, 40, 50, 60, 70, 80
Postorder20, 40, 30, 60, 80, 70, 50

Breadth-First Search (BFS)

Level by level, from left to right.

Result: 50, 30, 70, 20, 40, 60, 80

Implementation using a queue:

void level_order(Tree tree) {
    if (tree == NULL) return;

    Queue* q = create_queue();
    enqueue(q, tree);

    while (!is_queue_empty(q)) {
        Tree current = dequeue(q);
        printf("%d ", current->data);

        if (current->left != NULL)
            enqueue(q, current->left);
        if (current->right != NULL)
            enqueue(q, current->right);
    }
}

Tree Measurements

// Height
int height(Tree tree) {
    if (tree == NULL) return -1;

    int h_left = height(tree->left);
    int h_right = height(tree->right);

    return 1 + (h_left > h_right ? h_left : h_right);
}

// Number of nodes
int count_nodes(Tree tree) {
    if (tree == NULL) return 0;
    return 1 + count_nodes(tree->left) + count_nodes(tree->right);
}

// Minimum (leftmost node)
int find_min(Tree tree) {
    while (tree->left != NULL) {
        tree = tree->left;
    }
    return tree->data;
}

Complexity

OperationAverage caseWorst case (degenerate)
SearchO(log n)O(n)
InsertionO(log n)O(n)
DeletionO(log n)O(n)
Min/MaxO(log n)O(n)
Degenerate trees

If insertions are made in ascending/descending order, the tree degenerates into a linked list and loses its advantages. Solutions: AVL trees, red-black trees.

Deletion in a BST

Three cases:

  1. Leaf: simply delete it
  2. One child: replace with the child
  3. Two children: replace with the successor (minimum of the right subtree) or the predecessor (maximum of the left subtree)

Applications

  • Dictionaries and symbol tables
  • File systems (directories)
  • Syntax trees (compilers)
  • Decision trees (AI)
  • QuickSort (partitions like a BST)