123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /* tree.c -- tree support functions */
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "tree.h"
- /* local data type */
- typedef struct pair {
- Trnode * parent;
- Trnode * child;
- } Pair;
- /* protototypes for local functions */
- static Trnode * MakeNode(const Item * pi);
- static bool ToLeft(const Item * i1, const Item * i2);
- static bool ToRight(const Item * i1, const Item * i2);
- static void AddNode (Trnode * new_node, Trnode * root);
- static void InOrder(const Trnode * root, void (* pfun)(Item item));
- static Pair SeekItem(const Item * pi, const Tree * ptree);
- static void DeleteNode(Trnode **ptr);
- static void DeleteAllNodes(Trnode * ptr);
- /* function definitions */
- void InitializeTree(Tree * ptree)
- {
- ptree->root = NULL;
- ptree->size = 0;
- }
- bool TreeIsEmpty(const Tree * ptree)
- {
- if (ptree->root == NULL)
- return true;
- else
- return false;
- }
- bool TreeIsFull(const Tree * ptree)
- {
- if (ptree->size == MAXITEMS)
- return true;
- else
- return false;
- }
- int TreeItemCount(const Tree * ptree)
- {
- return ptree->size;
- }
- bool AddItem(const Item * pi, Tree * ptree)
- {
- Trnode * new_node;
-
- if (TreeIsFull(ptree))
- {
- fprintf(stderr,"Tree is full\n");
- return false; /* early return */
- }
- if (SeekItem(pi, ptree).child != NULL)
- {
- fprintf(stderr, "Attempted to add duplicate item\n");
- return false; /* early return */
- }
- new_node = MakeNode(pi); /* points to new node */
- if (new_node == NULL)
- {
- fprintf(stderr, "Couldn't create node\n");
- return false; /* early return */
- }
- /* succeeded in creating a new node */
- ptree->size++;
-
- if (ptree->root == NULL) /* case 1: tree is empty */
- ptree->root = new_node; /* new node is tree root */
- else /* case 2: not empty */
- AddNode(new_node,ptree->root); /* add node to tree */
-
- return true; /* successful return */
- }
- bool InTree(const Item * pi, const Tree * ptree)
- {
- return (SeekItem(pi, ptree).child == NULL) ? false : true;
- }
- bool DeleteItem(const Item * pi, Tree * ptree)
- {
- Pair look;
-
- look = SeekItem(pi, ptree);
- if (look.child == NULL)
- return false;
-
- if (look.parent == NULL) /* delete root item */
- DeleteNode(&ptree->root);
- else if (look.parent->left == look.child)
- DeleteNode(&look.parent->left);
- else
- DeleteNode(&look.parent->right);
- ptree->size--;
-
- return true;
- }
- void Traverse (const Tree * ptree, void (* pfun)(Item item))
- {
-
- if (ptree != NULL)
- InOrder(ptree->root, pfun);
- }
- void DeleteAll(Tree * ptree)
- {
- if (ptree != NULL)
- DeleteAllNodes(ptree->root);
- ptree->root = NULL;
- ptree->size = 0;
- }
- /* local functions */
- static void InOrder(const Trnode * root, void (* pfun)(Item item))
- {
- if (root != NULL)
- {
- InOrder(root->left, pfun);
- (*pfun)(root->item);
- InOrder(root->right, pfun);
- }
- }
- static void DeleteAllNodes(Trnode * root)
- {
- Trnode * pright;
-
- if (root != NULL)
- {
- pright = root->right;
- DeleteAllNodes(root->left);
- free(root);
- DeleteAllNodes(pright);
- }
- }
- static void AddNode (Trnode * new_node, Trnode * root)
- {
- if (ToLeft(&new_node->item, &root->item))
- {
- if (root->left == NULL) /* empty subtree */
- root->left = new_node; /* so add node here */
- else
- AddNode(new_node, root->left);/* else process subtree*/
- }
- else if (ToRight(&new_node->item, &root->item))
- {
- if (root->right == NULL)
- root->right = new_node;
- else
- AddNode(new_node, root->right);
- }
- else /* should be no duplicates */
- {
- fprintf(stderr,"location error in AddNode()\n");
- exit(1);
- }
- }
- static bool ToLeft(const Item * i1, const Item * i2)
- {
- int comp1;
-
- if ((comp1 = strcmp(i1->petname, i2->petname)) < 0)
- return true;
- else if (comp1 == 0 &&
- strcmp(i1->petkind, i2->petkind) < 0 )
- return true;
- else
- return false;
- }
- static bool ToRight(const Item * i1, const Item * i2)
- {
- int comp1;
-
- if ((comp1 = strcmp(i1->petname, i2->petname)) > 0)
- return true;
- else if (comp1 == 0 &&
- strcmp(i1->petkind, i2->petkind) > 0 )
- return true;
- else
- return false;
- }
- static Trnode * MakeNode(const Item * pi)
- {
- Trnode * new_node;
-
- new_node = (Trnode *) malloc(sizeof(Trnode));
- if (new_node != NULL)
- {
- new_node->item = *pi;
- new_node->left = NULL;
- new_node->right = NULL;
- }
-
- return new_node;
- }
- static Pair SeekItem(const Item * pi, const Tree * ptree)
- {
- Pair look;
- look.parent = NULL;
- look.child = ptree->root;
-
- if (look.child == NULL)
- return look; /* early return */
-
- while (look.child != NULL)
- {
- if (ToLeft(pi, &(look.child->item)))
- {
- look.parent = look.child;
- look.child = look.child->left;
- }
- else if (ToRight(pi, &(look.child->item)))
- {
- look.parent = look.child;
- look.child = look.child->right;
- }
- else /* must be same if not to left or right */
- break; /* look.child is address of node with item */
- }
-
- return look; /* successful return */
- }
- static void DeleteNode(Trnode **ptr)
- /* ptr is address of parent member pointing to target node */
- {
- Trnode * temp;
-
- if ( (*ptr)->left == NULL)
- {
- temp = *ptr;
- *ptr = (*ptr)->right;
- free(temp);
- }
- else if ( (*ptr)->right == NULL)
- {
- temp = *ptr;
- *ptr = (*ptr)->left;
- free(temp);
- }
- else /* deleted node has two children */
- {
- /* find where to reattach right subtree */
- for (temp = (*ptr)->left; temp->right != NULL;
- temp = temp->right)
- continue;
- temp->right = (*ptr)->right;
- temp = *ptr;
- *ptr =(*ptr)->left;
- free(temp);
- }
- }
|