Open In App

Introduction to Binary Tree

Last Updated : 14 Feb, 2025
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Share
Report
News Follow

Binary Tree is a non-linear and hierarchical data structure where each node has at most two children referred to as the left child and the right child.  The topmost node in a binary tree is called the root, and the bottom-most nodes are called leaves.

Introduction-to-Binary-Tree

Introduction to Binary Tree

Representation of Binary Tree

Each node in a Binary Tree has three parts:

  • Data
  • Pointer to the left child
  • Pointer to the right child
Binary-Tree-Representation

Binary Tree Representation

Create/Declare a Node of a Binary Tree

Syntax to declare a Node of Binary Tree in different languages:

C++
// Use any below method to implement Nodes of binary tree

// 1: Using struct
struct Node {
    int data;
    Node* left, * right;

    Node(int key) {
        data = key;
        left = nullptr;
        right = nullptr;
    }
};

// 2: Using class
class Node {
public:
    int data;
    Node* left, * right;

    Node(int key) {
        data = key;
        left = nullptr;
        right = nullptr;
    }
};
C Java Python C# JavaScript

Example for Creating a Binary Tree

Here’s an example of creating a Binary Tree with four nodes (2, 3, 4, 5)

Binary-Tree-with-three-nodes

Creating a Binary Tree having three nodes

C++
#include <iostream>
using namespace std;

struct Node{
    int data;
    Node *left, *right;
    Node(int d){
        data = d;
        left = nullptr;
        right = nullptr;
    }
};

int main(){
    // Initilize and allocate memory for tree nodes
    Node* firstNode = new Node(2);
    Node* secondNode = new Node(3);
    Node* thirdNode = new Node(4);
    Node* fourthNode = new Node(5);

    // Connect binary tree nodes
    firstNode->left = secondNode;
    firstNode->right = thirdNode;
    secondNode->left = fourthNode;
    return 0;
}
C Java Python C# JavaScript

In the above code, we have created four tree nodes firstNode, secondNode, thirdNode and fourthNode having values 2, 3, 4 and 5 respectively.

  • After creating three nodes, we have connected these node to form the tree structure like mentioned in above image.
  • Connect the secondNode to the left of firstNode by firstNode->left = secondNode
  • Connect the thirdNode to the right of firstNode by firstNode->right = thirdNode
  • Connect the fourthNode to the left of secondNode by secondNode->left = fourthNode

Terminologies in Binary Tree

  • Nodes: The fundamental part of a binary tree, where each node contains data and link to two child nodes.
  • Root: The topmost node in a tree is known as the root node. It has no parent and serves as the starting point for all nodes in the tree.
  • Parent Node: A node that has one or more child nodes. In a binary tree, each node can have at most two children.
  • Child Node: A node that is a descendant of another node (its parent).
  • Leaf Node: A node that does not have any children or both children are null.
  • Internal Node: A node that has at least one child. This includes all nodes except the root and the leaf nodes.
  • Depth of a Node: The number of edges from a specific node to the root node. The depth of the root node is zero.
  • Height of a Binary Tree: The number of nodes from the deepest leaf node to the root node.

The diagram below shows all these terms in a binary tree.

Terminologies-in-Binary-Tree-in-Data-Structure_1

Terminologies in Binary Tree in Data Structure

Properties of Binary Tree

  • The maximum number of nodes at level L of a binary tree is 2L
  • The maximum number of nodes in a binary tree of height H is 2H – 1
  • Total number of leaf nodes in a binary tree = total number of nodes with 2 children + 1
  • In a Binary Tree with N nodes, the minimum possible height or the minimum number of levels is Log2(N+1)
  • A Binary Tree with L leaves has at least | Log2L |+ 1 levels

Please refer Properties of Binary Tree for more details.

Types of Binary Tree

Binary Tree can be classified into multiples types based on multiple factors:

Operations On Binary Tree

Following is a list of common operations that can be performed on a binary tree:

1. Traversal in Binary Tree

Traversal in Binary Tree involves visiting all the nodes of the binary tree. Tree Traversal algorithms can be classified broadly into two categories, DFS and BFS:

Depth-First Search (DFS) algorithms: DFS explores as far down a branch as possible before backtracking. It is implemented using recursion. The main traversal methods in DFS for binary trees are:

Breadth-First Search (BFS) algorithms: BFS explores all nodes at the present depth before moving on to nodes at the next depth level. It is typically implemented using a queue. BFS in a binary tree is commonly referred to as Level Order Traversal.

Below is the implementation of traversals algorithm in binary tree:

C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* left, * right;

    Node(int d) {
        data = d;
        left = nullptr;
        right = nullptr;
    }
};

// In-order DFS: Left, Root, Right
void inOrderDFS(Node* node) {
    if (node == nullptr) return;

    inOrderDFS(node->left);
    cout << node->data << " ";
    inOrderDFS(node->right);
}

// Pre-order DFS: Root, Left, Right
void preOrderDFS(Node* node) {
    if (node == nullptr) return;

    cout << node->data << " ";
    preOrderDFS(node->left);
    preOrderDFS(node->right);
}

// Post-order DFS: Left, Right, Root
void postOrderDFS(Node* node) {
    if (node == nullptr) return;

    postOrderDFS(node->left);
    postOrderDFS(node->right);
    cout << node->data << " ";
}

void BFS(Node* root) {

    if (root == nullptr) return;
    queue<Node*> q;
    q.push(root);

    while (!q.empty()) {
        Node* node = q.front();
        q.pop(); 
        cout << node->data << " ";
        if (node->left != nullptr) q.push(node->left);
        if (node->right != nullptr) q.push(node->right);
        
    }
}

int main() {
    Node* root = new Node(2);
    root->left = new Node(3);
    root->right = new Node(4);
    root->left->left = new Node(5);

    cout << "In-order DFS: ";
    inOrderDFS(root);

    cout << "\nPre-order DFS: ";
    preOrderDFS(root);
   
    cout << "\nPost-order DFS: ";
    postOrderDFS(root);
  
    cout << "\nLevel order: ";
    BFS(root);

    return 0;
}
C Java Python C# JavaScript

Output
In-order DFS: 5 3 2 4 
Pre-order DFS: 2 3 5 4 
Post-order DFS: 5 3 4 2 
Level order: 2 3 4 5 

2. Insertion in Binary Tree

Inserting elements means add a new node into the binary tree. As we know that there is no such ordering of elements in the binary tree, So we do not have to worry about the ordering of node in the binary tree. We would first creates a root node in case of empty tree. Then subsequent insertions involve iteratively searching for an empty place at each level of the tree. When an empty left or right child is found then new node is inserted there. By convention, insertion always starts with the left child node.

Insertion-in-Binary-Tree

Insertion in Binary Tree

C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* left, * right;
    Node(int d) {
        data = d;
        left = right = nullptr;
    }
};

// Function to insert a new node in the binary tree
Node* insert(Node* root, int key) {
    // If the tree is empty, create the root node
    if (root == nullptr) {
        root = new Node(key);
        return root;
    }
    // Create a queue for level order traversal
    queue<Node*> q;
    q.push(root);

    // Do level order traversal until we find an empty place
    while (!q.empty()) {
        Node* temp = q.front();
        q.pop();

        // If left child is empty, insert the new node here
        if (temp->left == nullptr) {
            temp->left = new Node(key);
            break;
        } else {
            q.push(temp->left);
        }
        // If right child is empty, insert the new node here
        if (temp->right == nullptr) {
            temp->right = new Node(key);
            break;
        } else {
            q.push(temp->right);
        }
    }
    return root;
}

void inorder(Node* root) {
    if (root == nullptr) return;
    inorder(root->left);
    cout << root->data << " ";
    inorder(root->right);
}

int main() {
    Node* root = new Node(2);
    root->left = new Node(3);
    root->right = new Node(4) ; 
    root->left->left = new Node(5);
  
    cout << "Inorder traversal before insertion: ";
    inorder(root);
    cout << endl;

    int key = 6;
    root = insert(root, key);

    cout << "Inorder traversal after insertion: ";
    inorder(root);
    cout << endl;

    return 0;
}
C Java Python C# JavaScript

Output
Inorder traversal before insertion: 5 3 2 4 
Inorder traversal after insertion: 5 3 6 2 4 

3. Searching in Binary Tree

Searching for a value in a binary tree means looking through the tree to find a node that has that value. Since binary trees do not have a specific order like binary search trees, we typically use any traversal method to search. The most common methods are depth-first search (DFS) and breadth-first search (BFS). In DFS, we start from the root and explore the depth nodes first. In BFS, we explore all the nodes at the present depth level before moving on to the nodes at the next level. We continue this process until we either find the node with the desired value or reach the end of the tree. If the tree is empty or the value isn’t found after exploring all possibilities, we conclude that the value does not exist in the tree.

Here is the implementation of searching in a binary tree using Depth-First Search (DFS)

C++
#include <iostream>
using namespace std;

struct Node{
    int data;
    Node *left, *right;
    Node(int d){
        data = d;
        left = right = nullptr;
    }
};

// Function to search for a value in the binary tree using DFS
bool searchDFS(Node *root, int value){
    // Base case: If the tree is empty or we've reached a leaf node
    if (root == nullptr) return false;

    // If the node's data is equal to the value we are searching for
    if (root->data == value) return true;

    // Recursively search in the left and right subtrees
    bool left_res = searchDFS(root->left, value);
    bool right_res = searchDFS(root->right, value);

    return left_res || right_res;
}

int main()
{
    Node *root = new Node(2);
    root->left = new Node(3);
    root->right = new Node(4);
    root->left->left = new Node(5);
    root->left->right = new Node(6);

    int value = 6;
    if (searchDFS(root, value))
        cout << value << " is found in the binary tree" << endl;
    else
        cout << value << " is not found in the binary tree" << endl;

    return 0;
}
C Java Python C# JavaScript

Output
6 is found in the binary tree

4. Deletion in Binary Tree

Deleting a node from a binary tree means removing a specific node while keeping the tree’s structure. First, we need to find the node that want to delete by traversing through the tree using any traversal method. Then replace the node’s value with the value of the last node in the tree (found by traversing to the rightmost leaf), and then delete that last node. This way, the tree structure won’t be effected. And remember to check for special cases, like trying to delete from an empty tree, to avoid any issues.

Note: There is no specific rule of deletion but we always make sure that during deletion the binary tree proper should be preserved.

Deletion-in-Binary-Tree

Deletion in Binary Tree

C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* left, * right;
    Node(int d) {
        data = d;
        left = right = nullptr;
    }
};

// Function to delete a node from the binary tree
Node* deleteNode(Node* root, int val) {
    if (root == nullptr) return nullptr; 
    // Use a queue to perform BFS
    queue<Node*> q;
    q.push(root);
    Node* target = nullptr;

    // Find the target node
    while (!q.empty()) {
        Node* curr = q.front();
        q.pop();

        // Check for current node is the target node to delete
        if (curr->data == val) {
            target = curr;
            break;
        }
        // Add children to the queue
        if (curr->left) q.push(curr->left);
        if (curr->right) q.push(curr->right);
    }
    // If target node is not found, return the original tree
    if (target == nullptr) return root;

    // Find the deepest rightmost node and its parent
    pair<Node*, Node*> last = {nullptr, nullptr};
    queue<pair<Node*, Node*>> q1;
    q1.push({root, nullptr});
  
    while (!q1.empty()) {
        auto curr = q1.front();
        q1.pop();

        // Update the last
        last = curr;
      
        if (curr.first->left) 
          q1.push({curr.first->left, curr.first});
        if (curr.first->right) 
          q1.push({curr.first->right, curr.first});
    }

    Node* lastNode = last.first;
    Node* lastParent = last.second;

    // Replace target's value with the last node's value
    target->data = lastNode->data;

    // Remove the last node
    if (lastParent) {
        if (lastParent->left==lastNode)lastParent->left = nullptr;
        else lastParent->right = nullptr;
        delete lastNode;
    } else {
        // If the last node was the root
        delete lastNode;
        return nullptr;
    }
    return root;  
}

void inOrder(Node* root) {
    if (root == nullptr) return;
    inOrder(root->left);
    cout << root->data << " ";
    inOrder(root->right);
}

int main() {
    // Creating a simple binary tree
    Node *root = new Node(2);
    root->left = new Node(3);
    root->right = new Node(4);
    root->left->left = new Node(5);
    root->left->right = new Node(6);

    cout << "Original tree (in-order): ";
    inOrder(root);

    int valToDel = 3;
    root = deleteNode(root, valToDel);

    cout <<"\nTree after deleting " << valToDel << " (in-order): ";
    inOrder(root);
    cout << endl;

    return 0;
}
C Java Python C# JavaScript

Output
Original tree (in-order): 5 3 6 2 4 
Tree after deleting 3 (in-order): 5 6 2 4 

Auxiliary Operations On Binary Tree

Complexity Analysis of Binary Tree Operations

Here’s the complexity analysis for specific binary tree operations:

OperationTime ComplexityAuxiliary Space
In-Order TraversalO(n)O(n)
Pre-Order TraversalO(n)O(n)
Post-Order TraversalO(n)O(n)
Insertion (Unbalanced)O(n)O(n)
Searching (Unbalanced)O(n)O(n)
Deletion (Unbalanced)O(n)O(n)

Note: We can use Morris Traversal to traverse all the nodes of the binary tree in O(n) time complexity but with O(1) auxiliary space.

Advantages of Binary Tree

  • Efficient Search: Binary Search Trees (a variation of Binary Tree) are efficient when searching for a specific element, as each node has at most two child nodes when compared to linked list and arrays
  • Memory Efficient: Binary trees require lesser memory as compared to other tree data structures, therefore memory-efficient.
  • Binary trees are relatively easy to implement and understand as each node has at most two children, left child and right child.

Disadvantages of Binary Tree

  • Limited structure: Binary trees are limited to two child nodes per node, which can limit their usefulness in certain applications. For example, if a tree requires more than two child nodes per node, a different tree structure may be more suitable.
  • Unbalanced trees: Unbalanced binary trees, where one subtree is significantly larger than the other, can lead to inefficient search operations. This can occur if the tree is not properly balanced or if data is inserted in a non-random order.
  • Space inefficiency: Binary trees can be space inefficient when compared to other data structures like arrays and linked list. This is because each node requires two child references or pointers, which can be a significant amount of memory overhead for large trees.
  • Slow performance in worst-case scenarios: In the worst-case scenario, a binary tree can become degenerate or skewed, meaning that each node has only one child. In this case, search operations in Binary Search Tree (a variation of Binary Tree) can degrade to O(n) time complexity, where n is the number of nodes in the tree.

Applications of Binary Tree

  • Binary Tree can be used to represent hierarchical data.
  • Huffman Coding trees are used in data compression algorithms.
  • Priority Queue is another application of binary tree that is used for searching maximum or minimum in O(1) time complexity.
  • Useful for indexing segmented at the database is useful in storing cache in the system,
  • Binary trees can be used to implement decision trees, a type of machine learning algorithm used for classification and regression analysis.

Frequently Asked Questions (FAQs) on Binary Tree

1. What is a binary tree?

A binary tree is a non-linear data structure consisting of nodes, where each node has at most two children (left child and the right child).

2. What are the types of binary trees?

Binary trees can be classified into various types, including full binary trees, complete binary trees, perfect binary trees, balanced binary trees (such as AVL trees and Red-Black trees), and degenerate (or pathological) binary trees.

3. What is the height of a binary tree?

The height of a binary tree is the length of the longest path from the root node to a leaf node. It represents the number of edges in the longest path from the root node to a leaf node.

4. What is the depth of a node in a binary tree?

The depth of a node in a binary tree is the length of the path from the root node to that particular node. The depth of the root node is 0.

5. How do you perform tree traversal in a binary tree?

Tree traversal in a binary tree can be done in different ways: In-order traversal, Pre-order traversal, Post-order traversal, and Level-order traversal (also known as breadth-first traversal).

6. What is an Inorder traversal in Binary Tree?

In Inorder traversal, nodes are recursively visited in this order: left child, root, right child. This traversal results in nodes being visited in non-decreasing order in a binary search tree.

7. What is a Preorder traversal in Binary Tree?

In Preorder traversal, nodes are recursively visited in this order: root, left child, right child. This traversal results in root node being the first node to be visited.

8. What is a Postorder traversal in Binary Tree?

In Postorder traversal, nodes are recursively visited in this order: left child, right child and root. This traversal results in root node being the last node to be visited.

9. What is the difference between a Binary Tree and a Binary Search Tree?

A binary tree is a hierarchical data structure where each node has at most two children, whereas a binary search tree is a type of binary tree in which the left child of a node contains values less than the node’s value, and the right child contains values greater than the node’s value.

10. What is a balanced binary tree?

A balanced binary tree is a binary tree in which the height of the left and right subtrees of every node differ by at most one. Balanced trees help maintain efficient operations such as searching, insertion, and deletion with time complexities close to O(log n).

Conclusion:

Tree is a hierarchical data structure. Main uses of trees include maintaining hierarchical data, providing moderate access and insert/delete operations. Binary trees are special cases of tree where every node has at most two children.



Next Article
Article Tags :
Practice Tags :

Similar Reads

three90RightbarBannerImg