What’s New ?

The Top 10 favtutor Features You Might Have Overlooked

Read More

Print Bottom View of a Binary Tree (with code)

  • Sep 17, 2024
  • 7 Minutes Read
  • Why Trust Us
    We uphold a strict editorial policy that emphasizes factual accuracy, relevance, and impartiality. Our content is crafted by top technical writers with deep knowledge in the fields of computer science and data science, ensuring each piece is meticulously reviewed by a team of seasoned editors to guarantee compliance with the highest standards in educational content creation and publishing.
  • By Vedanti Kshirsagar
Print Bottom View of a Binary Tree (with code)

A binary tree is a widely used data structure in computer science that consists of nodes connected hierarchically. The bottom view of a binary tree provides valuable insights into its structure when viewed from a vertical perspective. In this article, we will understand the concept of the bottom view of a binary tree, and present an algorithm to obtain the bottom view with examples.

What is the Bottom View of a Binary Tree?

The bottom view of a binary tree refers to the set of nodes that are visible when the tree is observed from the bottom. Each node in the bottom view is associated with its horizontal distance from the root of the tree. Nodes sharing the same horizontal distance are considered at the same level, and the node with the highest level (closest to the bottom) is included in the bottom view.

But do we need to print the bottom view? Well, the bottom view provides an intuitive visual representation of the binary tree, emphasizing the nodes at the lowest levels.  It can be employed to extract essential information, such as the last visible node at each horizontal distance. 

Let's consider the following binary tree:

binary tree example

The bottom view of this binary tree, from left to right, would be: 4, 2, 6, 8, 7. These nodes are the last visible nodes at their respective horizontal distances when viewed from the bottom.

Approaches to Obtain the Bottom View

To find the bottom view of a binary tree, you can employ various traversal algorithms, including Depth-First Search (DFS), Breadth-First Search (BFS), and Level Order Traversal.

Let's explore how each of these methods can be used to determine the bottom view of a binary tree:

Depth-First Search (DFS)

DFS is a traversal algorithm that explores as far as possible along each branch before backtracking. In the context of finding the bottom view of a binary tree, you can use either the pre-order, in-order, or post-order traversal technique. However, the pre-order traversal is typically preferred.

Pre-order DFS Algorithm:

  • Start with the root node.
  • Traverse the left subtree recursively.
  • Traverse the right subtree recursively.
  • While traversing, maintain a horizontal distance for each node and keep track of the maximum and minimum horizontal distances.
  • Store the node's value and horizontal distance in a map or dictionary.
  • After traversing the entire tree, extract the values associated with the maximum horizontal distance for each level. These values represent the bottom view of the binary tree.

Here is the code:

#include 
#include 
using namespace std;

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

void dfs(TreeNode* root, int horizontalDistance, int level, map<int, pair<int, int>>& nodeMap) {
    if (root == nullptr) return;
    
    if (nodeMap.count(horizontalDistance) == 0 || level >= nodeMap[horizontalDistance].second) {
        nodeMap[horizontalDistance] = make_pair(root->val, level);
    }
    
    dfs(root->left, horizontalDistance - 1, level + 1, nodeMap);
    dfs(root->right, horizontalDistance + 1, level + 1, nodeMap);
}

void printBottomView(TreeNode* root) {
    map<int, pair<int, int>> nodeMap; // map to store horizontal distance, (value, level)
    dfs(root, 0, 0, nodeMap);
    
    for (const auto& entry : nodeMap) {
        cout << entry.second.first << " ";
    }
}

int main() {
    // Create a sample binary tree
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);
    root->right->left = new TreeNode(6);
    root->right->right = new TreeNode(7);
    root->right->left->right = new TreeNode(8);

    // Find and print the bottom view
    cout << "Bottom View: ";
    printBottomView(root);

    return 0;
}

 

Output:

Bottom View: 4 2 6 8 7 

 

The Time Complexity is O(n), where n is the number of nodes in the binary tree. Since we visit each node exactly once, the time complexity is linear.

 

Breadth-First Search (BFS)

BFS is a traversal algorithm that explores all the nodes at the same level before moving to the next level. This algorithm is well-suited for finding the bottom view of a binary tree.

BFS Algorithm:

  • Start with the root node and enqueue it into a queue.
  • Maintain a dictionary or map to store the horizontal distance of each node from the root.
  • While the queue is not empty:
    • Dequeue a node and update its horizontal distance in the dictionary.
    • Enqueue its left child (if present) with a decreased horizontal distance.
    • Enqueue its right child (if present) with an increased horizontal distance.
  • After traversing the entire tree, extract the values associated with the largest horizontal distance for each level. These values represent the bottom view of the binary tree.

Here is the code:

#include 
#include 
#include 
using namespace std;

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

void printBottomView(TreeNode* root) {
    if (root == nullptr) return;

    map<int, int> nodeMap; // map to store horizontal distance, value
    queue<pair<TreeNode*, int>> q; // queue to perform BFS

    q.push(make_pair(root, 0));

    while (!q.empty()) {
        TreeNode* node = q.front().first;
        int horizontalDistance = q.front().second;
        q.pop();

        nodeMap[horizontalDistance] = node->val;

        if (node->left)
            q.push(make_pair(node->left, horizontalDistance - 1));

        if (node->right)
            q.push(make_pair(node->right, horizontalDistance + 1));
    }

    for (const auto& entry : nodeMap) {
        cout << entry.second << " ";
    }
}

int main() {
    // Create a sample binary tree
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);
    root->right->left = new TreeNode(6);
    root->right->right = new TreeNode(7);
    root->right->left->right = new TreeNode(8);

    // Find and print the bottom view
    cout << "Bottom View: ";
    printBottomView(root);

    return 0;
}

 

Output:

Bottom View: 4 2 6 8 7 

 

The Time Complexity is O(n), where n is the number of nodes in the binary tree. Since we visit each node exactly once, the time complexity is linear.

Level Order Traversal

Level order traversal visits nodes level by level, starting from the root and moving to the next level before visiting the nodes in that level.

Level Order Traversal Algorithm:

  • Start with the root node and enqueue it into a queue.
  • Maintain a dictionary or map to store the horizontal distance of each node from the root.
  • While the queue is not empty:
    • Dequeue a node and update its horizontal distance in the dictionary.
    • Enqueue its left child (if present).
    • Enqueue its right child (if present).
  • After traversing the entire tree, extract the values associated with the largest horizontal distance for each level. These values represent the bottom view of the binary tree.

Here is the code:

#include 
#include 
#include 
using namespace std;

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

void printBottomView(TreeNode* root) {
    if (root == nullptr) return;

    map<int, int> nodeMap; // map to store horizontal distance, value
    queue<pair<TreeNode*, int>> q; // queue to perform level order traversal

    q.push(make_pair(root, 0));

    while (!q.empty()) {
        TreeNode* node = q.front().first;
        int horizontalDistance = q.front().second;
        q.pop();

        nodeMap[horizontalDistance] = node->val;

        if (node->left)
            q.push(make_pair(node->left, horizontalDistance - 1));

        if (node->right)
            q.push(make_pair(node->right, horizontalDistance + 1));
    }

    for (const auto& entry : nodeMap) {
        cout << entry.second << " ";
    }
}


int main() {
    // Create a sample binary tree
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);
    root->right->left = new TreeNode(6);
    root->right->right = new TreeNode(7);
    root->right->left->right = new TreeNode(8);

    // Find and print the bottom view
    cout << "Bottom View: ";
    printBottomView(root);

    return 0;
}

 

Output:

Bottom View: 4 2 6 8 7 

 

The Time Complexity is O(n), where n is the number of nodes in the binary tree. Since we visit each node exactly once, the time complexity is linear.

Conclusion

Overall, understanding the bottom view of a binary tree lets you see what nodes are visible if you were looking from below the tree. When you’re preparing for coding interviews, learning this concept can give you a nice edge. 

FavTutor - 24x7 Live Coding Help from Expert Tutors!

About The Author
Vedanti Kshirsagar
I am a fervid coder on LeetCode and have participated in various hackathons. I enjoy coding and learning new things in this field every day. I am a self-motivated, curious, and disciplined individual who looks forward to sharing and expanding my knowledge in any way possible