tree.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* tree.c -- tree support functions */
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include "tree.h"
  6. /* local data type */
  7. typedef struct pair {
  8. Trnode * parent;
  9. Trnode * child;
  10. } Pair;
  11. /* protototypes for local functions */
  12. static Trnode * MakeNode(const Item * pi);
  13. static bool ToLeft(const Item * i1, const Item * i2);
  14. static bool ToRight(const Item * i1, const Item * i2);
  15. static void AddNode (Trnode * new_node, Trnode * root);
  16. static void InOrder(const Trnode * root, void (* pfun)(Item item));
  17. static Pair SeekItem(const Item * pi, const Tree * ptree);
  18. static void DeleteNode(Trnode **ptr);
  19. static void DeleteAllNodes(Trnode * ptr);
  20. /* function definitions */
  21. void InitializeTree(Tree * ptree)
  22. {
  23. ptree->root = NULL;
  24. ptree->size = 0;
  25. }
  26. bool TreeIsEmpty(const Tree * ptree)
  27. {
  28. if (ptree->root == NULL)
  29. return true;
  30. else
  31. return false;
  32. }
  33. bool TreeIsFull(const Tree * ptree)
  34. {
  35. if (ptree->size == MAXITEMS)
  36. return true;
  37. else
  38. return false;
  39. }
  40. int TreeItemCount(const Tree * ptree)
  41. {
  42. return ptree->size;
  43. }
  44. bool AddItem(const Item * pi, Tree * ptree)
  45. {
  46. Trnode * new_node;
  47. if (TreeIsFull(ptree))
  48. {
  49. fprintf(stderr,"Tree is full\n");
  50. return false; /* early return */
  51. }
  52. if (SeekItem(pi, ptree).child != NULL)
  53. {
  54. fprintf(stderr, "Attempted to add duplicate item\n");
  55. return false; /* early return */
  56. }
  57. new_node = MakeNode(pi); /* points to new node */
  58. if (new_node == NULL)
  59. {
  60. fprintf(stderr, "Couldn't create node\n");
  61. return false; /* early return */
  62. }
  63. /* succeeded in creating a new node */
  64. ptree->size++;
  65. if (ptree->root == NULL) /* case 1: tree is empty */
  66. ptree->root = new_node; /* new node is tree root */
  67. else /* case 2: not empty */
  68. AddNode(new_node,ptree->root); /* add node to tree */
  69. return true; /* successful return */
  70. }
  71. bool InTree(const Item * pi, const Tree * ptree)
  72. {
  73. return (SeekItem(pi, ptree).child == NULL) ? false : true;
  74. }
  75. bool DeleteItem(const Item * pi, Tree * ptree)
  76. {
  77. Pair look;
  78. look = SeekItem(pi, ptree);
  79. if (look.child == NULL)
  80. return false;
  81. if (look.parent == NULL) /* delete root item */
  82. DeleteNode(&ptree->root);
  83. else if (look.parent->left == look.child)
  84. DeleteNode(&look.parent->left);
  85. else
  86. DeleteNode(&look.parent->right);
  87. ptree->size--;
  88. return true;
  89. }
  90. void Traverse (const Tree * ptree, void (* pfun)(Item item))
  91. {
  92. if (ptree != NULL)
  93. InOrder(ptree->root, pfun);
  94. }
  95. void DeleteAll(Tree * ptree)
  96. {
  97. if (ptree != NULL)
  98. DeleteAllNodes(ptree->root);
  99. ptree->root = NULL;
  100. ptree->size = 0;
  101. }
  102. /* local functions */
  103. static void InOrder(const Trnode * root, void (* pfun)(Item item))
  104. {
  105. if (root != NULL)
  106. {
  107. InOrder(root->left, pfun);
  108. (*pfun)(root->item);
  109. InOrder(root->right, pfun);
  110. }
  111. }
  112. static void DeleteAllNodes(Trnode * root)
  113. {
  114. Trnode * pright;
  115. if (root != NULL)
  116. {
  117. pright = root->right;
  118. DeleteAllNodes(root->left);
  119. free(root);
  120. DeleteAllNodes(pright);
  121. }
  122. }
  123. static void AddNode (Trnode * new_node, Trnode * root)
  124. {
  125. if (ToLeft(&new_node->item, &root->item))
  126. {
  127. if (root->left == NULL) /* empty subtree */
  128. root->left = new_node; /* so add node here */
  129. else
  130. AddNode(new_node, root->left);/* else process subtree*/
  131. }
  132. else if (ToRight(&new_node->item, &root->item))
  133. {
  134. if (root->right == NULL)
  135. root->right = new_node;
  136. else
  137. AddNode(new_node, root->right);
  138. }
  139. else /* should be no duplicates */
  140. {
  141. fprintf(stderr,"location error in AddNode()\n");
  142. exit(1);
  143. }
  144. }
  145. static bool ToLeft(const Item * i1, const Item * i2)
  146. {
  147. int comp1;
  148. if ((comp1 = strcmp(i1->petname, i2->petname)) < 0)
  149. return true;
  150. else if (comp1 == 0 &&
  151. strcmp(i1->petkind, i2->petkind) < 0 )
  152. return true;
  153. else
  154. return false;
  155. }
  156. static bool ToRight(const Item * i1, const Item * i2)
  157. {
  158. int comp1;
  159. if ((comp1 = strcmp(i1->petname, i2->petname)) > 0)
  160. return true;
  161. else if (comp1 == 0 &&
  162. strcmp(i1->petkind, i2->petkind) > 0 )
  163. return true;
  164. else
  165. return false;
  166. }
  167. static Trnode * MakeNode(const Item * pi)
  168. {
  169. Trnode * new_node;
  170. new_node = (Trnode *) malloc(sizeof(Trnode));
  171. if (new_node != NULL)
  172. {
  173. new_node->item = *pi;
  174. new_node->left = NULL;
  175. new_node->right = NULL;
  176. }
  177. return new_node;
  178. }
  179. static Pair SeekItem(const Item * pi, const Tree * ptree)
  180. {
  181. Pair look;
  182. look.parent = NULL;
  183. look.child = ptree->root;
  184. if (look.child == NULL)
  185. return look; /* early return */
  186. while (look.child != NULL)
  187. {
  188. if (ToLeft(pi, &(look.child->item)))
  189. {
  190. look.parent = look.child;
  191. look.child = look.child->left;
  192. }
  193. else if (ToRight(pi, &(look.child->item)))
  194. {
  195. look.parent = look.child;
  196. look.child = look.child->right;
  197. }
  198. else /* must be same if not to left or right */
  199. break; /* look.child is address of node with item */
  200. }
  201. return look; /* successful return */
  202. }
  203. static void DeleteNode(Trnode **ptr)
  204. /* ptr is address of parent member pointing to target node */
  205. {
  206. Trnode * temp;
  207. if ( (*ptr)->left == NULL)
  208. {
  209. temp = *ptr;
  210. *ptr = (*ptr)->right;
  211. free(temp);
  212. }
  213. else if ( (*ptr)->right == NULL)
  214. {
  215. temp = *ptr;
  216. *ptr = (*ptr)->left;
  217. free(temp);
  218. }
  219. else /* deleted node has two children */
  220. {
  221. /* find where to reattach right subtree */
  222. for (temp = (*ptr)->left; temp->right != NULL;
  223. temp = temp->right)
  224. continue;
  225. temp->right = (*ptr)->right;
  226. temp = *ptr;
  227. *ptr =(*ptr)->left;
  228. free(temp);
  229. }
  230. }