The find()
function should probably be:
int find(const BSTree tree, int data)
{
if (tree == 0) // or NULL
return 0;
else if (data == tree->data)
return 1;
else if (data < tree->data)
return find(tree->left, data);
else // if (data > tree->data)
return find(tree->right, data);
}
It's notable that you must have code equivalent to typedef struct SomeTag { … } *BSTree
somewhere in your system. On the whole, the answer to Is it a good idea to typedef
pointers is "No".
Your displayTree()
function is unexpectedly complex because you define it to take a BSTree *
instead of just a BSTree
. It should be:
void displayTree(const BSTree tree)
{
if (tree != NULL) // or 0
{
displayTree(tree->left);
printf("%d ", tree->data);
displayTree(tree->right);
}
}
The pointer-to-pointer is necessary in the insertSorted()
code, or you revise the prototype to:
BSTree *insertSorted(BSTree tree, int data).
and call it with:
tree = insertSorted(tree, data);
Both designs are feasible — there are some advantages each way.
MCVE
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct BSTree *BSTree;
struct BSTree
{
int data;
BSTree left;
BSTree right;
};
void displayTree(BSTree tree);
void insertSorted(BSTree *tree, int data);
int find(const BSTree tree, int data);
static int isEmpty(const BSTree tree)
{
return (tree == 0);
}
static BSTree emptyTree(void)
{
return 0;
}
static BSTree createNode(int data)
{
BSTree root = malloc(sizeof(*root));
if (root != 0)
{
root->data = data;
root->left = 0;
root->right = 0;
}
return root;
}
int main(void)
{
BSTree tree = emptyTree();
assert(isEmpty(tree));
// Insert 7 elements into the tree
int arr[7] = { 5, 10, 1, 3, 7, 18, 20 };
for (int i = 0; i < 7; i++)
{
insertSorted(&tree, arr[i]);
}
displayTree(tree);
putchar('\n');
for (int i = 0; i < 7; i++)
{
assert(find(tree, arr[i]));
}
assert(!find(tree, 19));
assert(!find(tree, 6));
return 0;
}
int find(const BSTree tree, int data)
{
if (tree == 0)
return 0;
else if (data == tree->data)
return 1;
else if (data < tree->data)
return find(tree->left, data);
else // if (data > tree->data)
return find(tree->right, data);
}
void insertSorted(BSTree *tree, int data)
{
if (*tree == NULL)
{
*tree = createNode(data);
}
else if (data < (*tree)->data)
{
insertSorted(&(*tree)->left, data);
}
else
{
insertSorted(&(*tree)->right, data);
}
}
void displayTree(BSTree tree)
{
if (tree != NULL)
{
displayTree(tree->left);
printf("%d ", tree->data);
displayTree(tree->right);
}
}
Output
1 3 5 7 10 18 20
Assertions firing in the question's code
Note that in the question, there are two trailing assertions:
assert(!find(tree, 18)); //Here the assert is activated
assert(!find(tree, 5));
As Devin Liu pointed out in the answer, these assertions should fire — you just ran a loop that checked whether the elements of the array were present with assert(find(tree, arr[i]));
, and both 5 and 18 are in the array (arr[0]
and arr[5]
), so the contrary assertion after the checking loop should fire.
Change 18 to 19, and 5 to 6 (say; many other changes are OK too) and the code works, as shown above.