Dear all,
How good is this function which implements level order traversal of
binary tree ?
I have another comment about this. The queue-based algorithm needs a
queue proportional to the sizeo of the tree. Effectively you are doing
a breadth first search.
A breadth first search can be made to require less space by using a
depth-first search instead, and using repeated depth-first searches
to /fake/ the effect of a breadth-first search.
This is done by repeatedly doing a breadth-first search whose depth is
limited, and iteratively increasing the depth. This is called
iterative deepening.
First you do a depth-first search which only goes to depth 0. Then you
do another one which goes to depth 1. Then you do one which goes to
depth 2, and so on.
Whenever you hit the bottom depth, you visit the nodes at that depth.
The storage you require is proportional to the depth of the tree, not
the number of nodes in it, and it can be done recursively.
/*
* helper function: visit nodes at specified depth.
* return 1 if something was visited, otherwise 0.
*/
static int visit_depth(struct node *node, int depth)
{
if (node != NULL) {
int left_visited, right_visited;
if (depth == 0) {
printf("%d\n", node->val);
return 1;
}
left_visited = visit_level(node->left, depth - 1);
right_visited = visit_level(node->right, depth - 1);
return left_visited || right_visited;
}
return 0;
}
[[Student exercise question: above, why didn't we write
return visit_level(node->left, level - 1) || visit_level(node-
and instead used the left_visited and right_visited variables?]]
Now given visit_depth above, we can simply write level_trav like this:
void level_trav(struct node *tree)
{
int depth;
/* keep increasing depth until no nodes are found at that depth */
for (depth = 0; visit_level(tree, depth); depth++)
{
/* empty */
}
}
Now you might think that the algoithm is slow because it keeps
revisiting the lower depths over and over again. But remember that
more than half of the nodes are in the bottom-most level that is
visited. Each time visit_level is called with a greater depth, it
visists more than twice as many nodes as in the previous iteration.
And this means that in the last iteration, it visits about as many
nodes as in all of the first iterations combined! This means that half
of the work is always in the last iteration! So the algorithm runs in
O(N) and basically the overhead for doing it this way is that you
traverse each node twice on average. Of course, the nodes at the
bottom level are visited only once (and that's more than half the
nodes in the tree!). And the root node is a high traffic corridor,
being a gateway to the rest of the tree: it is traversed in each
iteration.
Whether you want to do it this way or using the queue depends on how
large the tree is. Can you spare the O(N) queue storage? Or the tree
large enough that saving memory is worth traversing the nodes more
than once?