Skip to content

Trees🔗

  • Trees are heirarchical data structures consisting of nodes connected by edges.
  • Each tree has a root node, and zero or more child nodes forming a parent-child relationship without cycles.

Types of Trees🔗

Tree Type Description
Binary Tree Each node has at most two children (left and right).
Binary Search Tree (BST) A binary tree where left child < parent < right child, enabling efficient search operations.
Balanced Trees Trees maintaining height balance for efficient operations (e.g., AVL, Red-Black trees).
Heap Complete binary tree satisfying heap property (min-heap or max-heap).
Trie (Prefix Tree) Tree used for storing strings, where each node represents a character, enabling fast prefix queries.
Fenwick Tree (BIT) Binary Indexed Tree for efficient prefix sum queries and updates.
Segment Tree Tree structure to efficiently answer range queries and updates on arrays.
N-ary Tree Each node can have any number of children, generalizing binary trees.
Suffix Tree Compressed trie of all suffixes of a string, used in string processing.

Implementation🔗

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

Tree Traversal🔗

Traversal Type Description Order of Processing
Preorder Visit root, traverse left, right Root → Left → Right
Inorder Traverse left, visit root, right Left → Root → Right
Postorder Traverse left, right, visit root Left → Right → Root
Level Order Traverse level by level (BFS) Top to bottom, left to right per level

Traversal Implementation🔗

void preorder(TreeNode* root) {
    if (!root) return;
    cout << root->val << " ";
    preorder(root->left);
    preorder(root->right);
}

void inorder(TreeNode* root) {
    if (!root) return;
    inorder(root->left);
    cout << root->val << " ";
    inorder(root->right);
}

void postorder(TreeNode* root) {
    if (!root) return;
    postorder(root->left);
    postorder(root->right);
    cout << root->val << " ";
}

void levelOrderTraversal(TreeNode* root) {
    if (!root) return;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        TreeNode* node = q.front(); q.pop();
        cout << node->val << " ";
        if (node->left) q.push(node->left);
        if (node->right) q.push(node->right);
    }
}

Binary Search Trees🔗

  • NOTE: Inorder traversal of the BST returns a sorted list
#include <iostream>
using namespace std;

class BST {
private:
    struct Node {
        int key;
        Node *left, *right;
        Node(int k) : key(k), left(nullptr), right(nullptr) {}
    };

    Node* root;

    // Recursive search
    Node* search(Node* node, int key) {
        if (node == nullptr || node->key == key)
            return node;
        if (key < node->key)
            return search(node->left, key);
        else
            return search(node->right, key);
    }

    // Recursive insert
    void insert(Node*& node, int key) {
        if (node == nullptr) {
            node = new Node(key);
            return;
        }
        if (key < node->key)
            insert(node->left, key);
        else
            insert(node->right, key);
    }

public:
    BST() : root(nullptr) {}

    // Public API
    void insert(int key) { insert(root, key); }
    bool search(int key) { return search(root, key) != nullptr; }
};