Trying to print top view of a tree using two if statements
The solution is pretty easy if you print the left side by recursion and the right side using a simple while loop..
void for_left(node *root)
{
if(!root->left)
{
cout<<root->data<<" ";
return;
}
for_left(root->left);
cout<<root->data<<" ";
return;
}
void top_view(node * root)
{
for_left(root->left);
cout<<root->data<<" ";
while(root->right)
{
cout<<(root->right)->data<<" ";
root=root->right;
}
}
Your approach will work not because, when you call left
or right
subtree you will just stick to it. The problem with this approach is you are just driven by which side of the tree is called first.
May be you can solve it by using stack and queue as somebody else said but i feel that the following is a simpler and more intuitive approach:
(SEE THE CODE AT THE END, IT'S VERY SIMPLE)
The approach to solve this is by maintaining horizontal distance
from root and you print the first node for each different horizontal distance
.
What is horizontal distance?
I am just taking the image you have added.
Horizontal distance
for a particular node
is defined as the number of from root horizontally. If you see no.of edges that will become vertical distance.
To make things easier for all the nodes on left side of root start with negative horizontal distance and right side positive distance.
How do you calculate horizontal distance?
If you are going right add 1
, if you are going left add -1
.
so
horizontal distance of 3 = 0
horizontal distance of 5 = -1
horizontal distance of 1 = -2
horizontal distance of 9 = -1
horizontal distance of 4 = 0
horizontal distance of 2 = 1
horizontal distance of 6 = 0
horizontal distance of 7 = 2
horizontal distance of 8 = 1
Nodes 3,4,6
have same horizontal distance of 0
what does the mean?
That means when you see from top all these nodes are in a line vertically one above it.
If they are in a line vertically which one do you see?
The one which is can be reached first from root.
How do you find which one can be reached first?
as usual BFS
How this prints solution for your example?
There are five different horizontal distance value {-1,-2,0,1,2}
hor dist Nodes
0 - {3,6,8} // 3 comes first in BFS so print 3
-1 - {5,9} // 5 comes first in BFS so print 5
-2 - {1} // just print 1
1 - {2} // just print 2
2 - {7} // just print 7
So it will print {3,5,1,2,7}
HashSet<Integer> set = new HashSet<>();
Queue<QueueItem> queue = new LinkedList<>();
queue.add(new QueueItem(root, 0)); // Horizontal distance of root is 0
while (!queue.isEmpty())
{
QueueItem temp = queue.poll();
int hd = temp.hd;
TreeNode n = temp.node;
// If this is the first node at its horizontal distance,
// then this node is in top view
if (!set.contains(hd))
{
set.add(hd);
System.out.print(n.key + " ");
}
if (n.left != null)
queue.add(new QueueItem(n.left, hd-1));
if (n.right != null)
queue.add(new QueueItem(n.right, hd+1));
}
This problem can be very easily solved by using:
Stack: To print the root and the left subtree.
Queue: To print the right subtree.
Your function should be like this:
void topview(Node root)
{
if(root==null)
return;
Stack<Integer> s=new Stack<Integer>();
s.push(root.data);
Node root2=root;
while(root.left!=null)
{
s.push(root.left.data);
root=root.left;
}
while(s.size()!=0)
System.out.print(s.pop()+" ");
Queue<Integer> q=new LinkedList<Integer>();
q.add(root2.right.data);
root2=root2.right;
while(root2.right!=null)
{
q.add(root2.right.data);
root2=root2.right;
}
while(q.size()!=0)
System.out.print(q.poll()+" ");
}