| Shape Field: Name Sides Radius | Link Field: A pointer to a stack (or queue or linked list). |
| Data Structure | Stack | Queue | List | Binary Search Tree | Graph |
|---|---|---|---|---|---|
| Insertions | Top | Rear | Anywhere | Leaf Node | Edge |
| Deletions | Top | Front | Anywhere | Anywhere | Edge |
| Basic Structure | Linear | Linear | Linear | Hierarchical | Network |
Typically, we distinguish trees based on their representation, reserving the
term, tree, for structures that are encoded as dynamically linked
lists. We also could use an array encoding for a tree. Such structures are
generally called heaps to distinguish them from their dynamically linked
counterparts.
General Characteristics of Binary Search Trees
A binary search tree has the following characteristics
| Link to Left Child | Data Field(s) | Link To Right Child |
This traversal is abbreviated as NLR (Node, Left, Right). It
incorporates a stack algorithm and is usually coded as a recursive function. Its
name is derived from prefix notation. (A preorder traversal of an expression
tree produces the expression written in prefix notation.)
This traversal is abbreviated as LNR(Left, Node, Right). It also is a
stack algorithm and is coded as a recursive function. Its name is derived from
infix notation.
This traversal is abbreviated as LRN(Left, Right, Node). It also is a
stack algorithm and is coded as a recursive function. Its name is derived from
postfix notation.
This traversal has NO abbreviation. It is a queue algorithm, and is
encoded as an iterative function. Its name is derived from its traversal
pattern since it visits all the nodes on a level beginning with the leftmost
node. When it has finished with one level, it moves to the next lower level.
The TREE MENU 1. Add a node to the tree 2. Preorder Traversal 3. Inorder traversal 4. Postorder Traversal 5. Level Order Traversal 6. QUIT |
#include <stdio.h>
#include <stdlib.h>
#define IS_FULL(ptr) (!(ptr))
typedef struct node *tree_ptr;
typedef struct node {
tree_ptr left_child;
int key;
tree_ptr right_child;
};
char print_menu();
tree_ptr new_node();
void add_node(tree_ptr *, int);
void preorder(tree_ptr, int *);
void inorder(tree_ptr, int *);
void postorder(tree_ptr, int *);
void level_order(tree_ptr);
|
int main()
{
/* create a dynamically linked tree */
int choice = print_menu();
int num;
int level;
tree_ptr root;
root = NULL;
while (choice != 6) {
switch(choice) {
case 1: printf("Enter the number to insert: ");
scanf("%d",&num);
add_node(&root, num);
printf("\n\nThe tree contains\n\n");
level = 1;
preorder(root, &level);
break;
case 2: printf("\n\nPreorder traversal:\n\n");
level = 1;
preorder(root, &level);
break;
case 3: printf("\n\ninorder traversal:\n\n");
level = 0;
inorder(root, &level);
break;
case 4: printf("postorder traversal:\n\n");
level = 0;
postorder(root, &level);
break;
case 5: printf("level_order traversal:\n\n");
level_order(root);
}
choice = print_menu();
}
}
|
tree_ptr new_node()
{
/* get a new node, check to see if memory is full */
tree_ptr ptr = (tree_ptr) malloc(sizeof(struct node));
if (!ptr) {
fprintf(stderr, "The memory is full\n");
exit(1);
}
return ptr;
}
|
void add_node(tree_ptr *node, int num)
/* add a node to the tree */
/* pass in the address of the ptr to the current node */
{
tree_ptr ptr = *node;
if (!ptr) {
ptr = new_node();
ptr->key = num;
ptr->left_child = ptr->right_child = NULL;
*node = ptr;
}
else if (num == ptr->key)
fprintf(stderr, "The number is currently in the tree\n");
else if (num < ptr->key)
add_node(&ptr->left_child, num);
else
add_node(&ptr->right_child, num);
}
|
void preorder(tree_ptr ptr, int *level)
/* preorder tree traversal */
{
int i;
if (ptr) {
printf("Level %d:", *level);
for (i = 1; i <= *level; i++)
printf(" ");
printf("%d\n",ptr->key);
(*level)++;
preorder(ptr->left_child, level);
preorder(ptr->right_child, level);
(*level)--;
}
}
|
The following table contains a sample run.
Preorder traversal: Level 1: 60 Level 2: 50 Level 3: 40 Level 3: 55 Level 2: 70 Level 3: 65 Level 3: 80 Level 4: 75 |
The inorder traversal produces a sorted list of the nodes based on the key
value. The code is found in the following table.
void inorder(tree_ptr ptr, int *level)
/* inorder tree traversal */
{
int i;
if (ptr) {
(*level)++;
inorder(ptr->left_child, level);
printf("Level %d:", *level);
for(i = 1; i <= *level; i++)
printf(" ");
printf("%d\n",ptr->key);
inorder(ptr->right_child, level);
(*level)--;
}
}
|
inorder traversal: Level 3: 40 Level 2: 50 Level 3: 55 Level 1: 60 Level 3: 65 Level 2: 70 Level 4: 75 Level 3: 80 |
void postorder(tree_ptr ptr, int *level)
/* postorder tree traversal */
{
int i;
if (ptr) {
(*level)++;
postorder(ptr->left_child, level);
postorder(ptr->right_child, level);
printf("Level %d:", *level);
for (i=1; i <= *level; i++)
printf(" ");
printf("%d\n",ptr->key);
(*level)--;
}
}
|
postorder traversal: Level 3: 40 Level 3: 55 Level 2: 50 Level 3: 65 Level 4: 75 Level 3: 80 Level 2: 70 Level 1: 60 |
typedef struct queue *queue_ptr;
typedef struct queue {
tree_ptr key;
int level;
queue_ptr link;
};
void add_queue(queue_ptr *, queue_ptr *, tree_ptr, int);
void delete_queue(queue_ptr *, tree_ptr *, int *);
|
The delete_queue() function requires three parameters. The first
represents the pointer to the front pointer, the second represents the tree
node, and the last represents the level
The add_queue() function
The add_queue() function is conceptually identical to the public member
functions you created in C++. Unlike C++, where we can hide the front and rear
pointers from the public, we must pass these pointers in C. The code is found
in the following table.
void add_queue(queue_ptr *front, queue_ptr *rear, tree_ptr node, int level)
/* add a tree ptr to the queue */
{
queue_ptr temp = (queue_ptr) malloc(sizeof(struct queue));
if IS_FULL(temp) {
fprintf(stderr, "The memory is full\n");
exit(1);
}
temp->key = node;
temp->level = level;
temp->link = NULL;
if (!*front)
*front = temp;
else
(*rear)->link = temp;
*rear = temp;
}
|
void delete_queue(queue_ptr *front, tree_ptr *ptr, int *level)
/* delete a tree ptr from the queue */
{
queue_ptr temp;
tree_ptr node;
temp = *front;
if (*front) {
node = temp->key;
*level = temp->level;
*front = temp->link;
*ptr = node;
free(temp);
}
}
|
void level_order(tree_ptr root)
/* level_order tree traversal */
{
queue_ptr front, rear;
tree_ptr node;
int i, level;
front = rear = NULL;
add_queue(&front,&rear, root, 1);
do {
delete_queue(&front, &node,&level);
if (node) {
printf("Level: %d", level);
for (i=1; i<= level; i++)
printf(" ");
printf("%d\n",node->key);
if(node->left_child)
add_queue(&front,&rear,node->left_child,level+1);
if (node->right_child)
add_queue(&front,&rear,node->right_child, level+1);
}
} while (front);
}
|
level_order traversal: Level: 1 60 Level: 2 50 Level: 2 70 Level: 3 40 Level: 3 55 Level: 3 65 Level: 3 80 Level: 4 75 |