Launch your tech mastery with us—your coding journey starts now!
Course Content
Data Structure

Binary Trees

A Binary Tree is a tree where each node has at most two children, referred to as the left child and right child.

Binary Tree data structure illustration showing a root node connected to left and right child nodes, forming left and right subtrees, with each node having at most two children.

Properties of Binary Trees

  1. Maximum nodes at level L = 2^L (where root is at level 0)
  2. Maximum nodes in a tree of height H = 2^(H+1) – 1
  3. Minimum height for N nodes = log₂(N+1) – 1

Types of Binary Trees

1. Full Binary Tree

Every node has either 0 or 2 children (no node has only 1 child).

       1
      / \
     2   3
    / \
   4   5

2. Complete Binary Tree

All levels are completely filled except possibly the last, which is filled from left to right.

       1
      / \
     2   3
    / \  /
   4  5 6

3. Perfect Binary Tree

All internal nodes have 2 children and all leaves are at the same level.

       1
      / \
     2   3
    / \ / \
   4  5 6  7

4. Skewed Binary Tree

All nodes have only one child (either left or right).

    1           1
     \         /
      2       2
       \     /
        3   3

Binary Tree Implementation

java
class Node {
    int data;
    Node left, right;
    
    public Node(int item) {
        data = item;
        left = right = null;
    }
}

class BinaryTree {
    Node root;
    
    public BinaryTree() {
        root = null;
    }
    
    // Constructor with root value
    public BinaryTree(int data) {
        root = new Node(data);
    }
}

Binary Tree Traversals

There are three main ways to traverse a binary tree:

1. Inorder Traversal (Left → Root → Right)

Process:

  1. Visit left subtree
  2. Visit root
  3. Visit right subtree

Example:

Tree:
    1
   / \
  2   3
 / \
4   5

Inorder: 4 → 2 → 5 → 1 → 3

Code Example (Java):

java
class BinaryTree {
    Node root;
    
    // Inorder traversal: Left -> Root -> Right
    void inorderTraversal(Node node) {
        if (node == null)
            return;
        
        // First recur on left subtree
        inorderTraversal(node.left);
        
        // Then print the data of node
        System.out.print(node.data + " ");
        
        // Now recur on right subtree
        inorderTraversal(node.right);
    }
    
    // Wrapper method
    void inorder() {
        inorderTraversal(root);
    }
    
    // Main method to test
    public static void main(String[] args) {
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        
        System.out.println("Inorder Traversal:");
        tree.inorder();  // Output: 4 2 5 1 3
    }
}

2. Preorder Traversal (Root → Left → Right)

Process:

  1. Visit root
  2. Visit left subtree
  3. Visit right subtree

Example:

Tree:
    1
   / \
  2   3
 / \
4   5

Preorder: 1 → 2 → 4 → 5 → 3

Code Example (Java):

java
class BinaryTree {
    // Preorder traversal: Root -> Left -> Right
    void preorderTraversal(Node node) {
        if (node == null)
            return;
        
        // First print data of node
        System.out.print(node.data + " ");
        
        // Then recur on left subtree
        preorderTraversal(node.left);
        
        // Now recur on right subtree
        preorderTraversal(node.right);
    }
    
    // Wrapper method
    void preorder() {
        preorderTraversal(root);
    }
}

// Usage:
// tree.preorder();  // Output: 1 2 4 5 3

3. Postorder Traversal (Left → Right → Root)

Process:

  1. Visit left subtree
  2. Visit right subtree
  3. Visit root

Example:

Tree:
    1
   / \
  2   3
 / \
4   5

Postorder: 4 → 5 → 2 → 3 → 1

Code Example (Java):

 
 
java
class BinaryTree {
    // Postorder traversal: Left -> Right -> Root
    void postorderTraversal(Node node) {
        if (node == null)
            return;
        
        // First recur on left subtree
        postorderTraversal(node.left);
        
        // Then recur on right subtree
        postorderTraversal(node.right);
        
        // Now print the data of node
        System.out.print(node.data + " ");
    }
    
    // Wrapper method
    void postorder() {
        postorderTraversal(root);
    }
}

// Usage:
// tree.postorder();  // Output: 4 5 2 3 1

4. Level Order Traversal (Breadth-First)

Process: Visit nodes level by level from left to right.

java
import java.util.LinkedList;
import java.util.Queue;

class BinaryTree {
    // Level order traversal using Queue
    void levelOrder() {
        if (root == null)
            return;
        
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);
        
        while (!queue.isEmpty()) {
            Node tempNode = queue.poll();
            System.out.print(tempNode.data + " ");
            
            // Enqueue left child
            if (tempNode.left != null)
                queue.add(tempNode.left);
            
            // Enqueue right child
            if (tempNode.right != null)
                queue.add(tempNode.right);
        }
    }
}

// Usage:
// tree.levelOrder();  // Output: 1 2 3 4 5

Complete Binary Tree Example

java
class BinaryTree {
    Node root;
    
    // Calculate height of tree
    int height(Node node) {
        if (node == null)
            return 0;
        
        int leftHeight = height(node.left);
        int rightHeight = height(node.right);
        
        return Math.max(leftHeight, rightHeight) + 1;
    }
    
    // Count total nodes
    int countNodes(Node node) {
        if (node == null)
            return 0;
        
        return 1 + countNodes(node.left) + countNodes(node.right);
    }
    
    // Check if tree is full binary tree
    boolean isFullBinaryTree(Node node) {
        // If empty tree
        if (node == null)
            return true;
        
        // If leaf node
        if (node.left == null && node.right == null)
            return true;
        
        // If both left and right are not null, and left & right subtrees are full
        if ((node.left != null) && (node.right != null))
            return isFullBinaryTree(node.left) && isFullBinaryTree(node.right);
        
        // If none of the above
        return false;
    }
    
    public static void main(String[] args) {
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        
        System.out.println("Height of tree: " + tree.height(tree.root));
        System.out.println("Total nodes: " + tree.countNodes(tree.root));
        System.out.println("Is Full Binary Tree: " + tree.isFullBinaryTree(tree.root));
    }
}

Real-World Applications

  • Expression Trees: Used in compilers to parse expressions
  • Huffman Coding Trees: Data compression algorithms
  • Decision Trees: Machine learning and AI
  • File System Hierarchy: Organizing files and folders