This question was asked to me in an interview:
lets say we have above binary tree,how can i produce an output like below
2 7 5 2 6 9 5 11 4
i answered like may be we can have a leve开发者_开发问答l count variable and print all the elements sequentially by checking the level count variable of each node. probably i was wrong.
can anybody give anyidea as to how we can achieve that?
You need to do a breadth first traversal of the tree. Here it is described as follows:
Breadth-first traversal: Depth-first is not the only way to go through the elements of a tree. Another way is to go through them level-by-level.
For example, each element exists at a certain level (or depth) in the tree:
tree
----
j <-- level 0
/ \
f k <-- level 1
/ \ \
a h z <-- level 2
\
d <-- level 3
people like to number things starting with 0.)
So, if we want to visit the elements level-by-level (and left-to-right, as usual), we would start at level 0 with j, then go to level 1 for f and k, then go to level 2 for a, h and z, and finally go to level 3 for d.
This level-by-level traversal is called a breadth-first traversal because we explore the breadth, i.e., full width of the tree at a given level, before going deeper.
The traversal in your question is called a level-order traversal
and this is how it's done (very simple/clean code snippet I found).
You basically use a queue and the order of operations will look something like this:
enqueue F
dequeue F
enqueue B G
dequeue B
enqueue A D
dequeue G
enqueue I
dequeue A
dequeue D
enqueue C E
dequeue I
enqueue H
dequeue C
dequeue E
dequeue H
For this tree (straight from Wikipedia):
The term for that is level-order traversal. Wikipedia describes an algorithm for that using a queue:
levelorder(root)
q = empty queue
q.enqueue(root)
while not q.empty do
node := q.dequeue()
visit(node)
if node.left ≠ null
q.enqueue(node.left)
if node.right ≠ null
q.enqueue(node.right)
BFS:
std::queue<Node const *> q;
q.push(&root);
while (!q.empty()) {
Node const *n = q.front();
q.pop();
std::cout << n->data << std::endl;
if (n->left)
q.push(n->left);
if (n->right)
q.push(n->right);
}
Iterative deepening would also work and saves memory use, but at the expense of computing time.
If we are able to fetch the next element at same level, we are done. As per our prior knowledge, we can access these element using breadth first traversal.
Now only problem is how to check if we are at last element at any level. For this reason, we should be appending a delimiter (NULL in this case) to mark end of a level.
Algorithm:
1. Put root in queue.
2. Put NULL in queue.
3. While Queue is not empty
4. x = fetch first element from queue
5. If x is not NULL
6. x->rpeer <= top element of queue.
7. put left and right child of x in queue
8. else
9. if queue is not empty
10. put NULL in queue
11. end if
12. end while
13. return
#include <queue>
void print(tree* root)
{
queue<tree*> que;
if (!root)
return;
tree *tmp, *l, *r;
que.push(root);
que.push(NULL);
while( !que.empty() )
{
tmp = que.front();
que.pop();
if(tmp != NULL)
{
cout << tmp=>val; //print value
l = tmp->left;
r = tmp->right;
if(l) que.push(l);
if(r) que.push(r);
}
else
{
if (!que.empty())
que.push(NULL);
}
}
return;
}
I would use a collection, e.g. std::list
, to store all elements of the currently printed level:
- Collect pointers to all nodes in the current level in the container
- Print the nodes listed in the container
- Make a new container, add the subnodes of all nodes in the container
- Overwrite the old container with the new container
- repeat until container is empty
as an example of what you can do at an interview if you don't remember/don't know the "official" algorithm, my first idea was - traverse the tree in the regular pre-order dragging a level counter along, maintaining a vector of linked-lists of pointers to nodes per level, e.g.
levels[level].push_back(&node);
and in the end print the list of each level.
精彩评论