We have a binary tree, suppose like this:
8
/ \
6 10
/ \ / \
4 7 9 12
/ \
3 5
We have to print this binary tree in top-down manner - column wise. Note that, 8, 7 & 9
would be considered in same column. So the required output should be:
3
4
6 5
8 7 9
10
12
Currently I've implemented this problem using two maps, and one queue. Here's the method traversal(Node<T> node)
, which is invoked first time, passing the root node:
public void traverse(Node<T> node) {
Queue<Node<T>> queue = new LinkedList<>();
Map<Integer, List<Node<T>>> columnMap = new TreeMap<>();
Map<Node<T>, Integer> map = new HashMap<>();
queue.add(node);
while (!queue.isEmpty()) {
Node<T> temp = queue.poll();
if (map.isEmpty()) {
map.put(temp, 0);
columnMap.put(0, new ArrayList<Node<T>>(Arrays.asList(temp)));
}
int column = map.get(temp);
if (temp.left() != null) {
queue.add(temp.left());
if (columnMap.containsKey(column - 1)) {
columnMap.get(column - 1).add(temp.left());
} else {
columnMap.put(column - 1, new ArrayList<Node<T>>(Arrays.asList(temp.left())));
}
map.put(temp.left(), column - 1);
}
if (temp.right() != null) {
queue.add(temp.right());
if (columnMap.containsKey(column + 1)) {
columnMap.get(column + 1).add(temp.right());
} else {
columnMap.put(column + 1, new ArrayList<Node<T>>(Arrays.asList(temp.right())));
}
map.put(temp.right(), column + 1);
}
}
for (Entry<Integer, List<Node<T>>> entry: columnMap.entrySet()) {
System.out.println("Column - " + entry.getKey() + " : " + entry.getValue());
}
}
The idea is, starting from root node as column number 0
, the left node will have column number -1
, and the right node will have column number 1
. Then the right node of the left node will again have column number 0
. And similarly I proceed till I've exhausted all the nodes. I've used level order traversal for traversing.
The first map - Map<Node<T>, Integer>
is used to get the column number for a particular node. I've used this map, so that I can get the column number of a node in O(1)
time. For example, starting with root, I put a mapping - <root, 0>
, in the map. And then, put an entry in columnMap
- <0, root>
, specifying there is currently root
at column 0
. I've used Queue
for the purpose of level-order traversal (Well, it can be avoided by using pre-order, post-order or in-order).
Now, I remove the root
from queue
, and push it's two children. For left
child, I've to find the column number based on it's parent (in this case, root
). So, I get the column number for root
from map
. And subtract 1
from it to get column of left
. If the column number is already in the columnMap
, I just update the existing list of node for that column, else I add a new entry.
I thought of getting it done with just a single map, but I found it more clear.
Is there some better option? Currently, the code looks a bit complex to me. May be it can be improvised? I'm open to a completely different implementation too, provided it is more clear, and space and time efficient.