Print nodes in top view of Binary Tree | Set 2
Top view of a binary tree is the set of nodes visible when the tree is viewed from the top. Given a binary tree, print the top view of it. The output nodes should be printed from left to right.
Note: A node x is there in output if x is the topmost node at its horizontal distance. Horizontal distance of the left child of a node x is equal to the horizontal distance of x minus 1, and that of right child is the horizontal distance of x plus 1.
Input:
1
/ \
2 3
/ \ / \
4 5 6 7
Output: Top view: 4 2 1 3 7
Input:
1
/ \
2 3
\
4
\
5
\
6
Output: Top view: 2 1 3 6
The idea is to do something similar to Vertical Order Traversal. Like Vertical Order Traversal, we need to group nodes of same horizontal distance together. We do a level order traversal so that the topmost node at a horizontal node is visited before any other node of same horizontal distance below it. A Map is used to map the horizontal distance of the node with the node’s Data and vertical distance of the node.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
int hd;
struct Node* left;
struct Node* right;
};
struct Node* newNode( int data)
{
struct Node* node = new Node;
node->data = data;
node->hd = INT_MAX;
node->left = NULL;
node->right = NULL;
return node;
}
void printTopViewUtil(Node* root, int height,
int hd, map< int , pair< int , int > >& m)
{
if (root == NULL)
return ;
if (m.find(hd) == m.end()) {
m[hd] = make_pair(root->data, height);
}
else {
pair< int , int > p = (m.find(hd))->second;
if (p.second > height) {
m.erase(hd);
m[hd] = make_pair(root->data, height);
}
}
printTopViewUtil(root->left, height + 1, hd - 1, m);
printTopViewUtil(root->right, height + 1, hd + 1, m);
}
void printTopView(Node* root)
{
map< int , pair< int , int > > m;
printTopViewUtil(root, 0, 0, m);
for (map< int , pair< int , int > >::iterator it = m.begin();
it != m.end(); it++) {
pair< int , int > p = it->second;
cout << p.first << " " ;
}
}
int main()
{
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->right = newNode(4);
root->left->right->right = newNode(5);
root->left->right->right->right = newNode(6);
cout << "Top View : " ;
printTopView(root);
return 0;
}
|
Java
import java.util.*;
class GFG {
static class Node {
int data;
Node left;
Node right;
};
static class pair {
int data, height;
public pair( int data, int height)
{
this .data = data;
this .height = height;
}
}
static Node newNode( int data)
{
Node node = new Node();
node.data = data;
node.left = null ;
node.right = null ;
return node;
}
static void printTopViewUtil(Node root, int height,
int hd,
Map<Integer, pair> m)
{
if (root == null )
return ;
if (!m.containsKey(hd)) {
m.put(hd, new pair(root.data, height));
}
else {
pair p = m.get(hd);
if (p.height >= height) {
m.put(hd, new pair(root.data, height));
}
}
printTopViewUtil(root.left, height + 1 , hd - 1 , m);
printTopViewUtil(root.right, height + 1 , hd + 1 , m);
}
static void printTopView(Node root)
{
Map<Integer, pair> m = new TreeMap<>();
printTopViewUtil(root, 0 , 0 , m);
for (Map.Entry<Integer, pair> it : m.entrySet()) {
pair p = it.getValue();
System.out.print(p.data + " " );
}
}
public static void main(String[] args)
{
Node root = newNode( 1 );
root.left = newNode( 2 );
root.right = newNode( 3 );
root.left.right = newNode( 4 );
root.left.right.right = newNode( 5 );
root.left.right.right.right = newNode( 6 );
System.out.print( "Top View : " );
printTopView(root);
}
}
|
Python3
from collections import OrderedDict
class newNode:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
self .hd = 2 * * 32
def printTopViewUtil(root, height, hd, m):
if (root = = None ):
return
if hd not in m :
m[hd] = [root.data, height]
else :
p = m[hd]
if p[ 1 ] > height:
m[hd] = [root.data, height]
printTopViewUtil(root.left,
height + 1 , hd - 1 , m)
printTopViewUtil(root.right,
height + 1 , hd + 1 , m)
def printTopView(root):
m = OrderedDict()
printTopViewUtil(root, 0 , 0 , m)
for i in sorted ( list (m)):
p = m[i]
print (p[ 0 ], end = " " )
root = newNode( 1 )
root.left = newNode( 2 )
root.right = newNode( 3 )
root.left.right = newNode( 4 )
root.left.right.right = newNode( 5 )
root.left.right.right.right = newNode( 6 )
print ( "Top View : " , end = "")
printTopView(root)
|
C#
using System;
using System.Collections.Generic;
class GFG{
class Node
{
public int data;
public Node left;
public Node right;
};
class pair
{
public int data, height;
public pair( int data, int height)
{
this .data = data;
this .height = height;
}
}
static Node newNode( int data)
{
Node node = new Node();
node.data = data;
node.left = null ;
node.right = null ;
return node;
}
static void printTopViewUtil(Node root, int height,
int hd,
SortedDictionary< int , pair> m)
{
if (root == null )
return ;
if (!m.ContainsKey(hd))
{
m[hd] = new pair(root.data, height);
}
else
{
pair p = m[hd];
if (p.height >= height)
{
m[hd] = new pair(root.data, height);
}
}
printTopViewUtil(root.left, height + 1,
hd - 1, m);
printTopViewUtil(root.right, height + 1,
hd + 1, m);
}
static void printTopView(Node root)
{
SortedDictionary< int ,
pair> m = new SortedDictionary< int ,
pair>();
printTopViewUtil(root, 0, 0, m);
foreach ( var it in m.Values)
{
Console.Write(it.data + " " );
}
}
public static void Main( string [] args)
{
Node root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.right = newNode(4);
root.left.right.right = newNode(5);
root.left.right.right.right = newNode(6);
Console.Write( "Top View : " );
printTopView(root);
}
}
|
Javascript
<script>
class Node
{
constructor()
{
this .data = 0;
this .left = null ;
this .right = null ;
}
};
class pair
{
constructor(data, height)
{
this .data = data;
this .height = height;
}
}
function newNode(data)
{
var node = new Node();
node.data = data;
node.left = null ;
node.right = null ;
return node;
}
function printTopViewUtil(root, height, hd, m)
{
if (root == null )
return ;
if (!m.has(hd))
{
m.set(hd, new pair(root.data, height));
}
else
{
var p = m.get(hd);
if (p.height >= height)
{
m.set(hd, new pair(root.data, height));
}
}
printTopViewUtil(root.left, height + 1,
hd - 1, m);
printTopViewUtil(root.right, height + 1,
hd + 1, m);
}
function printTopView(root)
{
var m = new Map();
printTopViewUtil(root, 0, 0, m);
for ( var it of [...m].sort())
{
document.write(it[1].data + " " );
}
}
var root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.right = newNode(4);
root.left.right.right = newNode(5);
root.left.right.right.right = newNode(6);
document.write( "Top View : " );
printTopView(root);
</script>
|
Output
Top View : 2 1 3 6
Complexity Analysis:
- Time complexity: O(n) where n is number of nodes of binary tree
- Auxiliary space: O(n) for call stack
Approach#2: Using deque
We use a level order traversal technique to traverse the tree and maintain a dictionary to store the horizontal distance of each node from the root node. We keep adding nodes to the queue along with their horizontal distance from the root node. Then, we traverse the dictionary and print the values of the nodes with the minimum horizontal distance from the root node.
Algorithm
1. Create an empty dictionary to store the horizontal distance of each node from the root node.
2. Create a queue and enqueue the root node along with its horizontal distance, which is zero.
3. Traverse the tree using a level order traversal technique:
a. Dequeue a node and its horizontal distance from the queue.
b. If the horizontal distance is not present in the dictionary, add the node’s value to the dictionary with its horizontal distance.
c. Enqueue the left child of the dequeued node with its horizontal distance decreased by 1.
d. Enqueue the right child of the dequeued node with its horizontal distance increased by 1.
4. Traverse the dictionary and print the values of the nodes with the minimum horizontal distance from the root node.
C++
#include <iostream>
#include <map>
#include <deque>
class Node {
public :
int val;
Node* left;
Node* right;
Node( int value) : val(value), left(nullptr), right(nullptr) {}
};
void topView(Node* root) {
std::map< int , int > hdMap;
std::deque<std::pair<Node*, int >> q;
q.push_back(std::make_pair(root, 0));
while (!q.empty()) {
Node* node = q.front().first;
int hd = q.front().second;
q.pop_front();
if (hdMap.find(hd) == hdMap.end()) {
hdMap[hd] = node->val;
}
if (node->left) {
q.push_back(std::make_pair(node->left, hd - 1));
}
if (node->right) {
q.push_back(std::make_pair(node->right, hd + 1));
}
}
for ( auto it = hdMap.begin(); it != hdMap.end(); ++it) {
std::cout << it->second << " " ;
}
}
int main() {
Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
root->right->left = new Node(6);
root->right->right = new Node(7);
std::cout << "Top view: " ;
topView(root);
return 0;
}
|
Java
import java.util.*;
class Node {
int val;
Node left;
Node right;
public Node( int val) {
this .val = val;
this .left = null ;
this .right = null ;
}
}
public class Main {
public static void topView(Node root) {
if (root == null ) {
return ;
}
Map<Integer, Integer> hdMap = new TreeMap<>();
Queue<Node> queue = new LinkedList<>();
Queue<Integer> hdQueue = new LinkedList<>();
queue.offer(root);
hdQueue.offer( 0 );
while (!queue.isEmpty()) {
Node currNode = queue.poll();
int currHd = hdQueue.poll();
if (!hdMap.containsKey(currHd)) {
hdMap.put(currHd, currNode.val);
}
if (currNode.left != null ) {
queue.offer(currNode.left);
hdQueue.offer(currHd - 1 );
}
if (currNode.right != null ) {
queue.offer(currNode.right);
hdQueue.offer(currHd + 1 );
}
}
for ( int hd : hdMap.keySet()) {
System.out.print(hdMap.get(hd) + " " );
}
}
public static void main(String[] args) {
Node root = new Node( 1 );
root.left = new Node( 2 );
root.right = new Node( 3 );
root.left.left = new Node( 4 );
root.left.right = new Node( 5 );
root.right.left = new Node( 6 );
root.right.right = new Node( 7 );
System.out.print( "Top view: " );
topView(root);
}
}
|
Python3
from collections import deque
class Node:
def __init__( self , val):
self .val = val
self .left = None
self .right = None
def top_view(root):
hd_dict = {}
q = deque([(root, 0 )])
while q:
node, hd = q.popleft()
if hd not in hd_dict:
hd_dict[hd] = node.val
if node.left:
q.append((node.left, hd - 1 ))
if node.right:
q.append((node.right, hd + 1 ))
for hd in sorted (hd_dict.keys()):
print (hd_dict[hd], end = ' ' )
root = Node( 1 )
root.left = Node( 2 )
root.right = Node( 3 )
root.left.left = Node( 4 )
root.left.right = Node( 5 )
root.right.left = Node( 6 )
root.right.right = Node( 7 )
print ( "Top view: " , end = '')
top_view(root)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class Node
{
public int val;
public Node left;
public Node right;
public Node( int val)
{
this .val = val;
left = null ;
right = null ;
}
}
public class BinaryTree
{
public static void TopView(Node root)
{
Dictionary< int , int > hdDict = new Dictionary< int , int >();
Queue<(Node, int )> queue = new Queue<(Node, int )>();
queue.Enqueue((root, 0));
while (queue.Count > 0)
{
(Node node, int hd) = queue.Dequeue();
if (!hdDict.ContainsKey(hd))
{
hdDict[hd] = node.val;
}
if (node.left != null )
{
queue.Enqueue((node.left, hd - 1));
}
if (node.right != null )
{
queue.Enqueue((node.right, hd + 1));
}
}
foreach ( int hd in hdDict.Keys.OrderBy(key => key))
{
Console.Write(hdDict[hd] + " " );
}
}
}
class Program
{
static void Main( string [] args)
{
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
Console.Write( "Top view: " );
BinaryTree.TopView(root);
}
}
|
Javascript
class Node {
constructor(val) {
this .val = val;
this .left = null ;
this .right = null ;
}
}
function topView(root) {
const hdMap = {};
const queue = [{ node: root, hd: 0 }];
while (queue.length !== 0) {
const { node, hd } = queue.shift();
if (!(hd in hdMap)) {
hdMap[hd] = node.val;
}
if (node.left !== null ) {
queue.push({ node: node.left, hd: hd - 1 });
}
if (node.right !== null ) {
queue.push({ node: node.right, hd: hd + 1 });
}
}
Object.keys(hdMap)
.sort((a, b) => a - b)
.forEach(hd => process.stdout.write(hdMap[hd] + ' ' ));
}
const root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
process.stdout.write( "Top view: " );
topView(root);
|
Output
Top view: 4 2 1 3 7
Time Complexity: O(N), where N is the number of nodes in the binary tree, as we need to visit each node once.
Space Complexity: O(N), where N is the maximum number of nodes at any level in the binary tree, as we need to store the horizontal distance of each node from the root node. Additionally, we need to store the nodes in the queue, which can have at most N nodes in the worst case when the tree is a complete binary tree.
Last Updated :
23 Dec, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...