Summary and Analysis

Trees Library

Terms

Tree Creation and Destruction Functions, page 2

page 1 of 2

One of the most useful features of the tree data structure is that it can
grow dynamically. That is, at any point in your code, you can make a new
node and add it to the tree. Because of this you do not need to know the
number of nodes beforehand. As a result, our function which will provide
a new tree structure will need to allocate memory. Recall that we have
a tree_t data type, defined as follows:

From this definition we can see that each node points to its left and right
children. To make our node creation function mesh easily with the rest of
our implementation, it should return a pointer to the memory we allocate.
Here is one possible way to implementation such a function:

Since each node in the tree will necessarily be allocated dynamically,
it must also be freed when it is no longer needed. The following function
will take care of the freeing of an individual node.

void free_node (tree_t *tree)
{
if (tree != NULL) {
free(tree);
}
}

While it is useful to have a function that destroys an individual node,
it would be far more useful if we could make one function call to destroy
an entire tree. We mentioned in the introduction that trees are naturally
recursive. This function will take advantage of that feature. Destroying
a tree essentially requires destroying the tree headed by the left child and
the tree headed by the right child along with the root of the tree itself.
With that algorithm in mind, we produce the following function:

To break down the function above, we see that there is a base case for the
NULL tree, a recursive case for other trees, and finally a call to free_node
to destroy the tree's root. You will find that this is a pattern that recurs
frequently when writing functions to manipulate trees.