After each change to the tree in the testing program, we call
verify_tree() to check that the tree's structure and content are what
we think they should be. This function runs through a full gamut of
checks, with the following outline:
/* Checks that tree is well-formed
and verifies that the values in array[] are actually in tree.
There must be n elements in array[] and tree.
Returns nonzero only if no errors detected. */
staticint verify_tree (structbst_table *tree, intarray[], size_tn) {intokay = 1;
<@xref{\NODE\, , Check tree.>->bst_count is correct,110}
if (okay) { <@xref{\NODE\, , Check BST structure.>,111} }if (okay) { <@xref{\NODE\, , Check that the tree contains all the elements it should.>,115} }if (okay) { <@xref{\NODE\, , Check that forward traversal works.>,116} }if (okay) { <@xref{\NODE\, , Check that backward traversal works.>,117} }if (okay) { <@xref{\NODE\, , Check that traversal from the null element works.>,118} }returnokay;
}
This code is included in @refalso{98
The first step just checks that the number of items passed in as n is
the same as tree->bst_count.
/* Check tree's bst_count against that supplied. */
if (bst_count (tree) != n) {printf ("Treecountis%lu,butshouldbe%lu.\n",
(unsignedlong) bst_count (tree), (unsignedlong) n);
okay = 0;
}
This code is included in @refalso{109
Next, we verify that the BST has proper structure and that it has the
proper number of items. We'll do this recursively because that's
easiest and most obviously correct way. Function
recurse_verify_tree() for this returns the number of nodes in the BST.
After it returns, we verify that this is the expected number.
The function recurse_verify_tree() does the recursive verification.
It checks that nodes' values increase down to the right and decrease
down to the left. We also use it to count the number of nodes actually
in the tree:
/* Examines the binary tree rooted at node.
Zeroes *okay if an error occurs. Otherwise, does not modify *okay.
Sets *count to the number of nodes in that tree, including node itself if node != NULL.
All the nodes in the tree are verified to be at least min but no greater than max. */
staticvoid recurse_verify_tree (structbst_node *node, int *okay, size_t *count,
intmin, intmax) {intd; /* Value of this node's data. */
size_tsubcount[2]; /* Number of nodes in subtrees. */
if (node == NULL) {
*count = 0;
return;
}d = *(int *) node->bst_data;
<@xref{\NODE\, , Verify binary search tree ordering.>,114}
recurse_verify_tree (node->bst_link[0], okay, &subcount[0], min, d- 1);
recurse_verify_tree (node->bst_link[1], okay, &subcount[1], d+ 1, max);
*count = 1 +subcount[0] +subcount[1];
}
The third step is to check that the BST indeed contains all of the items
that it should:
/* Check that all the values in array[] are in tree. */
size_ti;
for (i = 0; i<n; i++)
if (bst_find (tree, &array[i]) == NULL) {printf ("Treedoesnotcontainexpectedvalue%d.\n", array[i]);
okay = 0;
}
This code is included in @refalso{109
The final steps all check traversal of the BST, first by traversing in
forward order from the beginning to the end, then in reverse order, then
by checking that the null item behaves correctly. The forward traversal
checks that the proper number of items are in the BST. It could appear
to have too few items if the tree's pointers are screwed up in one way,
or it could appear to have too many items if they are screwed up in
another way. We try to figure out how many items actually appear in the
tree during traversal, but give up if the count gets to be more than
twice that expected, assuming that this indicates a "loop" that will
cause traversal to never terminate.
/* Check that bst_t_first() and bst_t_next() work properly. */
structbst_traversertrav;
size_ti;
intprev = -1;
int *item;
for (i = 0, item = bst_t_first (&trav, tree); i< 2 * n && item != NULL;
i++, item = bst_t_next (&trav)) {if (*item<= prev) {printf ("Treeoutoforder:%dfollows%dintraversal\n", *item, prev);
okay = 0;
}prev = *item;
}if (i != n) {printf ("Treeshouldhave%luitems,buthas%luintraversal\n",
(unsignedlong) n, (unsignedlong) i);
okay = 0;
}
This code is included in @refalso{109
We do a similar traversal in the reverse order:
/* Check that bst_t_last() and bst_t_prev() work properly. */
structbst_traversertrav;
size_ti;
intnext = INT_MAX;
int *item;
for (i = 0, item = bst_t_last (&trav, tree); i< 2 * n && item != NULL;
i++, item = bst_t_prev (&trav)) {if (*item>= next) {printf ("Treeoutoforder:%dprecedes%dintraversal\n", *item, next);
okay = 0;
}next = *item;
}if (i != n) {printf ("Treeshouldhave%luitems,buthas%luinreverse\n",
(unsignedlong) n, (unsignedlong) i);
okay = 0;
}
This code is included in @refalso{109
The final check to perform on the traverser is to make sure that the
traverser null item works properly. We start out a traverser at the
null item with bst_t_init(), then make sure that the next item after
that, as reported by bst_t_next(), is the same as the item returned by
bst_t_init(), and similarly for the previous item:
Please take a moment to fill out
this visitor survey You can help support this site by
visiting the advertisers that sponsor it! (only once each, though)