Implementing a Binary Tree in Java

A binary tree is a hierarchical data structure composed of the nodes. Each node contains the value and references to its left child node and right child node, which are also binary trees that are possibly null. The structure resembles the tree with the nodes branching out from a central root, where each node have at most two children such as the left child node and the right child node.

The binary tree finds applications in different domains like computer science algorithms, database indexing, file systems etc. They offer efficient search, insertion and deletion operations when the appropriate balanced. In this Java, we will explore the basics of the binary tree. The implementation is focused on simplicity and clarity, it provides a solid foundation for understanding more advanced binary tree concepts and their applications.

Organization of Binary Tree in Java

Representation of Binary Tree:

Explanation of the Image:

  • The root node of the binary tree is 8.
  • The left child of the root has value 3 and it children are 1 and 6, and 6 has 2 children i.e. 4 and 7.
  • The right child of the root has 10 and its children are 13 and 14.
  • 1, 4, 7, 13 and 14 are leaf nodes which are without any children.

Implementation of Binary Tree:

Java
// Node Class
class Node {
    int key;
    Node left, right;

    public Node(int item) {
        key = item;
        left = right = null;
    }
}

// BinaryTree Class
public class BinaryTree {
    Node root;

    public BinaryTree() {
        root = null;
    }

    // Method to insert a new node with given key
    public void insert(int key) {
        root = insertRec(root, key);
    }

    // A recursive function to insert a new key in BST 
    private Node insertRec(Node root, int key) {
        // If the tree is empty, return a new node
        if (root == null) {
            root = new Node(key);
            return root;
        }

        // Otherwise, recur down the tree 
        if (key < root.key)
            root.left = insertRec(root.left, key);
        else if (key > root.key)
            root.right = insertRec(root.right, key);

        // return the (unchanged) node pointer 
        return root;
    }

    // Method to print the tree inorder
    public void inorder() {
        inorderRec(root);
    }

    // A utility function to do inorder traversal of BST
    private void inorderRec(Node root) {
        if (root != null) {
            inorderRec(root.left);
            System.out.print(root.key + " ");
            inorderRec(root.right);
        }
    }

    // Method to search for a key in the tree
    public boolean search(int key) {
        return searchRec(root, key);
    }

    // A utility function to search for a key in BST
    private boolean searchRec(Node root, int key) {
        if (root == null)
            return false;

        if (root.key == key)
            return true;

        if (key < root.key)
            return searchRec(root.left, key);
        else
            return searchRec(root.right, key);
    }

    // Method to find the minimum value in the tree
    public int findMin() {
        return findMinRec(root);
    }

    // A utility function to find the minimum value in BST
    private int findMinRec(Node root) {
        if (root == null)
            throw new IllegalStateException("Tree is empty");

        if (root.left == null)
            return root.key;

        return findMinRec(root.left);
    }

    // Method to find the maximum value in the tree
    public int findMax() {
        return findMaxRec(root);
    }

    // A utility function to find the maximum value in BST
    private int findMaxRec(Node root) {
        if (root == null)
            throw new IllegalStateException("Tree is empty");

        if (root.right == null)
            return root.key;

        return findMaxRec(root.right);
    }

    public static void main(String[] args) {
        BinaryTree tree = new BinaryTree();

        // Insert some nodes
        tree.insert(50);
        tree.insert(30);
        tree.insert(20);
        tree.insert(40);
        tree.insert(70);
        tree.insert(60);
        tree.insert(80);

        // Print inorder traversal of the tree
        System.out.println("Inorder traversal:");
        tree.inorder();
           // Output: 20 30 40 50 60 70 80

        // Search for a key
        int searchKey = 40;
        if (tree.search(searchKey))
            System.out.println("\nKey " + searchKey + " found in the tree.");
        else
            System.out.println("\nKey " + searchKey + " not found in the tree.");

        // Find minimum and maximum values
        System.out.println("Minimum value in the tree: " + tree.findMin());
        System.out.println("Maximum value in the tree: " + tree.findMax());
    }
}

Output
Inorder traversal:
20 30 40 50 60 70 80 
Key 40 found in the tree.
Minimum value in the tree: 20
Maximum value in the tree: 80

Complexity of the above Program:

Operation

Explanation

Complexity

Insertion

  • This operation is used to insert a new node into binary tree.
  • The time complexity of insertion operation is O(log n).
  • The space complexity of insertion operation is O(1).

Deletion

  • This operation is used to remove a node from binary tree.
  • The time complexity of deletion operation is O(log n).
  • The space complexity of deletion operation is O(1).

Traversal

  • This operation involves the 3 types of traversals such as: Inorder Traversal, Preorder Traversal, Post order Traversal.
  • Inorder Traversal is defined as the visit the left subtree after that visit current node and then visit right subtree.
  • Preorder Traversal is defined as it visit the current node after that visit left subtree and then visit right subtree.
  • Postorder Traversal is defined as it visit left subtree after that visit right subtree and then visit current node.
  • The time complexity of traversal is O(n).
  • The space complexity of traversal is O(log n).

Searching

  • This operation is used to find the specific key or value in binary tree.
  • The time complexity of searching is O(log n).
  • The space complexity of searching is O(1).

Height/Depth Calculation

  • This operation is used to calculate the maximum height of binary tree.
  • The time complexity of height calculation is O(n).
  • The space complexity of height calculation is O(log n).

Balanced Checking

  • This operation is used to check the binary tree is balanced or not.
  • The time complexity of balanced checking is O(n).
  • The space complexity of balanced checking is O(log n).

Finding Minimum/Maximum

  • This operation is used to find the maximum value or minimum value in binary tree.
  • The time complexity of finding minimum/maximum is O(log n).
  • The space complexity of finding minimum/maximum is O(1).

Applications of Binary Tree

Binary trees find applications in different domains due to their efficient structure for the organizing and manipulating the data. Some of the basic applications of binary tree are:

  1. Binary Search Trees (BST)
  2. Expression Evaluation
  3. Binary Heaps
  4. Balanced Binary Trees
  5. Binary Tree Traversal Algorithms
  6. File Systems
  7. Game Trees
  8. Huffman Encoding
  9. Trie Data Structure