Binary Search Tree (BST)

A Binary Search Tree is a binary tree where:

  • Left child < Node < Right child
  • Every left/right subtree is also a BST
  • No duplicate values (in general)
  • Duplicates, if allowed, are handled via special rules (e.g., frequency count)

The inorder traversal of BST will always result in a sorted array

Why Use BST?

  • Faster search, insert, and delete: O(log N) on average everytime in BST
  • Unbalanced binary trees can degrade to O(N) time when screwed, but not BST.

Return Target val in BST O(log₂N)

TreeNode* searchBST(TreeNode* root, int val) {
    while (root != NULL && root->val != val ){
        root = root->val < val ? root->right : root->left;
    }
    return root;
}

Floor in BST

  • Floor of a value refers to the value of the largest node in the BST that is smaller than or equal to the given key.
int floorInBST(TreeNode* root, int key){
    int floor = -1;
        
    while(root != nullptr){
        if(root->val == key){
            floor = root->val;
            return floor;
        }
            
        if(key > root->val){
            floor = root->val;
            root = root->right;
        } else {
            root = root->left;
        }
    }
    return floor;
}

Ceil in BST

  • Ceil of a value refers to the value of the smallest node in the BST that is greater than or equal to the given key.
int ceilInBST(TreeNode* root, int key){
    int ceil = -1;
        
    while(root != nullptr){
        if(root->val == key){
            ceil = root->val;
            return ceil;
        }
            
        if(key > root->val){
            root = root->right;
        } else {
            ceil = root->val;
            root = root->left;
        }
    }
    return ceil;
}

Insert a given Node in BST so as the tree remains a BST after insertion

class Solution {
public:
    Node* insertNode(Node* root, int key) {
        if (root == nullptr) return new Node(key);

        if (key < root->val) // If key is less, insert in left subtree
            root->left = insertNode(root->left, key); 
        else // If key is greater, insert in right subtree
            root->right = insertNode(root->right, key);

        return root;
    }
};

Delete a Node in Binary Search Tree

class Solution {
public:
    // Find the minimum value node in a subtree
    Node* findMin(Node* root) {
        while (root->left)
            root = root->left;
        return root;
    }

    Node* deleteNode(Node* root, int key) {
        if (root == nullptr) return nullptr;

        if (key < root->val) // If key is less, go to left subtree
            root->left = deleteNode(root->left, key);
        else if (key > root->val) // If key is greater, go to right subtree
            root->right = deleteNode(root->right, key);
        else {
            // Node with only one child or no child
            if (root->left == nullptr)
                return root->right;
            else if (root->right == nullptr)
                return root->left;

            // Node with two children: get inorder successor from right
            Node* temp = findMin(root->right);
            root->val = temp->val; // swap
            root->right = deleteNode(root->right, temp->val);
        }

        return root;
    }
};

Kth Smallest Element in a BST

  • using the idea that inorder traversal of BST is always sorted, so we can maintain a count of nodes till k nodes.
class Solution {
public:
    void inorder(TreeNode* root, int k, int &count, int &ans){
        if (root == nullptr) return;
        inorder(root->left, k, count, ans);
        count++;
        if (count == k){
            ans = root->val;
        }
        inorder(root->right, k, count, ans);
    }
    int kthSmallest(TreeNode* root, int k) {
        int count = 0;
        int ans;
        inorder(root, k, count, ans);
        return ans;
    }
};