Binary Tree - (Theory)


Binary Tree Theory & Implementation (Java)


1. Fundamentals of Binary Trees

1.1 Basic Definitions


2. Binary Tree Node Definition in Java

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    
    TreeNode(int x) {
        val = x;
    }
}

3. Tree Construction

3.1 Insert Node (Binary Tree - Level Order)

Not BST. For binary tree (not sorted), insert at the first empty spot level-wise.

public TreeNode insert(TreeNode root, int val) {
    if (root == null) return new TreeNode(val);

    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);

    while (!queue.isEmpty()) {
        TreeNode curr = queue.poll();
        if (curr.left == null) {
            curr.left = new TreeNode(val);
            break;
        } else queue.add(curr.left);

        if (curr.right == null) {
            curr.right = new TreeNode(val);
            break;
        } else queue.add(curr.right);
    }
    return root;
}

Time Complexity: O(N) (worst case, full traversal)
Space Complexity: O(N) for queue


3.2 Delete Node in Binary Tree

Remove the deepest node and replace it with the target node to be deleted.

public TreeNode delete(TreeNode root, int val) {
    if (root == null) return null;
    if (root.left == null && root.right == null) {
        return root.val == val ? null : root;
    }

    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    TreeNode target = null, last = null, parentOfLast = null;

    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        if (node.val == val) target = node;
        if (node.left != null) {
            parentOfLast = node;
            last = node.left;
            queue.add(node.left);
        }
        if (node.right != null) {
            parentOfLast = node;
            last = node.right;
            queue.add(node.right);
        }
    }

    if (target != null) {
        target.val = last.val;
        if (parentOfLast.right == last) parentOfLast.right = null;
        else parentOfLast.left = null;
    }
    return root;
}

4. Tree Traversals

4.1 DFS - Recursive Traversals

Inorder: Left → Root → Right

void inorder(TreeNode root) {
    if (root == null) return;
    inorder(root.left);
    System.out.print(root.val + " ");
    inorder(root.right);
}

Preorder: Root → Left → Right

void preorder(TreeNode root) {
    if (root == null) return;
    System.out.print(root.val + " ");
    preorder(root.left);
    preorder(root.right);
}

Postorder: Left → Right → Root

void postorder(TreeNode root) {
    if (root == null) return;
    postorder(root.left);
    postorder(root.right);
    System.out.print(root.val + " ");
}

Time and Space Complexities (All)


4.2 DFS - Stack-Based Iterative Traversals

Inorder (Iterative)

void inorderIterative(TreeNode root) {
    Stack<TreeNode> stack = new Stack<>();
    TreeNode curr = root;
    while (curr != null || !stack.isEmpty()) {
        while (curr != null) {
            stack.push(curr);
            curr = curr.left;
        }
        curr = stack.pop();
        System.out.print(curr.val + " ");
        curr = curr.right;
    }
}

Preorder (Iterative)

void preorderIterative(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode curr = stack.pop();
        System.out.print(curr.val + " ");
        if (curr.right != null) stack.push(curr.right);
        if (curr.left != null) stack.push(curr.left);
    }
}

Postorder (Two Stacks)

void postorderIterative(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> s1 = new Stack<>();
    Stack<TreeNode> s2 = new Stack<>();
    s1.push(root);
    while (!s1.isEmpty()) {
        TreeNode node = s1.pop();
        s2.push(node);
        if (node.left != null) s1.push(node.left);
        if (node.right != null) s1.push(node.right);
    }
    while (!s2.isEmpty()) System.out.print(s2.pop().val + " ");
}

4.3 BFS - Level Order

void levelOrder(TreeNode root) {
    if (root == null) return;
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode curr = queue.poll();
        System.out.print(curr.val + " ");
        if (curr.left != null) queue.add(curr.left);
        if (curr.right != null) queue.add(curr.right);
    }
}

Time Complexity: O(N)
Space Complexity: O(N)


5. Important Binary Tree Patterns

5.1 Height of Tree

int height(TreeNode root) {
    if (root == null) return 0;
    return 1 + Math.max(height(root.left), height(root.right));
}

5.2 Diameter of Tree (Longest Path)

int maxDiameter = 0;
int diameter(TreeNode root) {
    dfs(root);
    return maxDiameter;
}

int dfs(TreeNode node) {
    if (node == null) return 0;
    int left = dfs(node.left);
    int right = dfs(node.right);
    maxDiameter = Math.max(maxDiameter, left + right);
    return 1 + Math.max(left, right);
}

5.3 Check if Balanced

boolean isBalanced(TreeNode root) {
    return dfs(root) != -1;
}

int dfs(TreeNode node) {
    if (node == null) return 0;
    int left = dfs(node.left);
    int right = dfs(node.right);
    if (left == -1 || right == -1 || Math.abs(left - right) > 1) return -1;
    return 1 + Math.max(left, right);
}

5.4 Symmetric Tree

boolean isSymmetric(TreeNode root) {
    return root == null || isMirror(root.left, root.right);
}

boolean isMirror(TreeNode t1, TreeNode t2) {
    if (t1 == null || t2 == null) return t1 == t2;
    return t1.val == t2.val && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left);
}

6. Formulas and Observations


7. Space & Time Complexities Summary

Operation Time Space
Insert (Level Order) O(N) O(N)
Delete (Level Order) O(N) O(N)
Traversals (DFS/BFS) O(N) O(H)/O(N)
Height / Diameter O(N) O(H)
Check Balanced O(N) O(H)