Detailed Notes on Binary Search Trees (BSTs)

Definition of Binary Search Tree (BST)

  • A binary tree in symmetric order.

  • It can be either:

    • Empty

    • Two disjoint binary trees (left and right).

  • Keys are ordered such that:

    • Each node's key is larger than all keys in its left subtree.

    • Each node's key is smaller than all keys in its right subtree.

Anatomy of a Binary Tree

  • Structure consists of nodes with links to left and right children.

  • Example keys: A, C, E, H, R, S, X

Operations on BSTs

Search
  • Process:

    • If key < current node, go left.

    • If key > current node, go right.

    • If key == current node, search successful.

Insert
  • Process:

    • If key < current node, go left.

    • If key > current node, go right.

    • If null link is reached, insert the new node.

Structure in Java
  • A Node consists of:

    • Key and Value

    • References to left and right subtrees

  • BST is a class composed of a root Node.

Get Operation

  • Returns value associated with a key if found, else returns null.

  • Cost: Number of comparisons equals depth of node.

Put Operation

  • Associates a value with a given key:

    • If key exists, reset value.

    • If not, add a new node.

  • Cost: Similar to Get operation.

Insertion Characteristics

  • The shape of the BST is influenced by the order of insertion:

    • Best Case: Balanced tree

    • Worst Case: Degenerate tree (linked list)

  • Average compares for search/insert: ~ 2 ln(N), where N is the number of distinct keys inserted.

Floor and Ceiling Operations

Floor
  • The largest key ≤ a given key.

Ceiling
  • The smallest key ≥ a given key.

Deletion in BSTs

General Method
  • To delete a node with key:

    • Set its value to null (lazy deletion).

    • For true node removal, consider cases based on children:

    • No Children: Remove node by setting parent's link to null.

    • One Child: Link parent to child node.

    • Two Children: Find successor, delete the minimum in the right subtree.

Deleting Minimum
  • Traverse left until a node without left child is found, then replace with right child.

BST Tree Characteristics

  • Height of a random BST

    • Expected: ~ 4.311 ln(N)

    • Worst-case height is N-1.

Summary of Time Complexities

Operation

Complexity

Search

O(h)

Insert

O(h)

Delete

O(h)

Average cost (random order)

~1.39 ln(N)

Min/Max

O(h)

Floor/Ceiling

O(h)

Rank, Select

O(h)

In-order Traversal

O(N)

Closing Notes

  • BST allows for efficient ordered operations on keys, maintaining a logarithmic performance average if balanced.

class Node {
    int key, value;
    Node left, right;
    Node(int key, int value) {
        this.key = key;
        this.value = value;
        left = right = null;
    }
}

class BST {
    Node root;

    // Insert operation
    public void insert(int key, int value) {
        root = insertRec(root, key, value);
    }

    private Node insertRec(Node root, int key, int value) {
        if (root == null) {
            root = new Node(key, value);
            return root;
        }
        if (key < root.key) {
            root.left = insertRec(root.left, key, value);
        } else if (key > root.key) {
            root.right = insertRec(root.right, key, value);
        } else { // Update value if the key already exists
            root.value = value;
        }
        return root;
    }

    // Search operation
    public Node search(int key) {
        return searchRec(root, key);
    }

    private Node searchRec(Node root, int key) {
        if (root == null || root.key == key) {
            return root;
        }
        return key < root.key ? searchRec(root.left, key) : searchRec(root.right, key);
    }

    // In-Order Traversal
    public void inorder() {
        inorderRec(root);
    }

    private void inorderRec(Node root) {
        if (root != null) {
            inorderRec(root.left);
            System.out.print(" " + root.key);
            inorderRec(root.right);
        }
    }

    // Find Minimum
    public Node findMin() {
        return findMinRec(root);
    }

    private Node findMinRec(Node root) {
        return root.left == null ? root : findMinRec(root.left);
    }

    // Find Maximum
    public Node findMax() {
        return findMaxRec(root);
    }

    private Node findMaxRec(Node root) {
        return root.right == null ? root : findMaxRec(root.right);
    }

    // Find Floor
    public Node floor(int key) {
        return floorRec(root, key);
    }

    private Node floorRec(Node root, int key) {
        if (root == null) return null;
        if (root.key == key) return root;
        return key < root.key ? floorRec(root.left, key) : (floorRec(root.right, key) != null ? floorRec(root.right, key) : root);
    }

    // Find Ceiling
    public Node ceiling(int key) {
        return ceilingRec(root, key);
    }

    private Node ceilingRec(Node root, int key) {
        if (root == null) return null;
        if (root.key == key) return root;
        return key > root.key ? ceilingRec(root.right, key) : (ceilingRec(root.left, key) != null ? ceilingRec(root.left, key) : root);
    }
}

This code defines a basic Binary Search Tree with methods for insertion, searching by key, in-order traversal, finding the minimum and maximum keys, as well as calculating the floor and ceiling for a given key.