抽象数据类型(ADT)——二叉查找树

作者:追风剑情 发布于:2020-4-24 13:21 分类:C

示例:储存宠物

tree.h

  1. //#pragma once
  2. /* tree.h -- 二叉查找数 */
  3. /* 树中不允许有重复的项 */
  4. #ifndef _TREE_H_
  5. #define _TREE_H_
  6. #include <stdbool.h>
  7.  
  8. /* 根据具体情况重新定义 Item */
  9. #define SLEN 20
  10. typedef struct item
  11. {
  12. char petname[SLEN];
  13. char petkind[SLEN];
  14. } Item;
  15.  
  16. #define MAXITEMS 10
  17.  
  18. typedef struct trnode
  19. {
  20. Item item;
  21. struct trnode * left; /* 指向左分支的指针 */
  22. struct trnode * right;/* 指向右分支的指针 */
  23. } Trnode;
  24.  
  25. typedef struct tree
  26. {
  27. Trnode * root; /* 指向根节点的指针 */
  28. int size; /* 树的项数 */
  29. } Tree;
  30.  
  31. /* 函数原型 */
  32.  
  33. /* 操作: 把树初始化为空 */
  34. /* 前提条件: ptree指向一个树 */
  35. /* 后置条件: 树被初始化为空 */
  36. void InitializeTree(Tree * ptree);
  37.  
  38. /* 操作: 确定树是否为空 */
  39. /* 前提条件: ptree指向一个树 */
  40. /* 后置条件: 如果树为空,该函数返回true */
  41. /* 否则,返回false */
  42. bool TreeIsEmpty(const Tree * ptree);
  43.  
  44. /* 操作: 确定树是否已满 */
  45. /* 前提条件: ptree指向一个树 */
  46. /* 后置条件: 如果树已满,该函数返回true */
  47. /* 否则,返回false */
  48. bool TreeIsFull(const Tree * ptree);
  49.  
  50. /* 操作: 确定树的项数 */
  51. /* 前提条件: ptree指向一个树 */
  52. /* 后置条件: 返回树的项数 */
  53. int TreeItemCount(const Tree * ptree);
  54.  
  55. /* 操作: 在树中添加一个项 */
  56. /* 前提条件: pi是待添加项的地址 */
  57. /* ptree指向一个已初始化的树 */
  58. /* 后置条件: 如果可以添加,该函数将在树中添加一个项 */
  59. /* 并返回true;否则,返回false */
  60. bool AddItem(const Item * pi, Tree * ptree);
  61.  
  62. /* 操作: 在树中查找一个项 */
  63. /* 前提条件: pi指向一个项 */
  64. /* ptree指向一个已初始化的树 */
  65. /* 后置条件: 如果在树中找到一个项,该函数返回true */
  66. /* 否则,返回false */
  67. bool InTree(const Item * pi, const Tree * ptree);
  68.  
  69. /* 操作: 从树中删除一个项 */
  70. /* 前提条件: pi是删除项的地址 */
  71. /* ptree指向一个已初始化的树 */
  72. /* 后置条件: 如果从树中成功删除一个项,该函数返回true */
  73. /* 否则,返回false */
  74. bool DeleteItem(const Item * pi, Tree * ptree);
  75.  
  76. /* 操作: 把函数应用于树中的每一项 */
  77. /* 前提条件: ptree指向一个树 */
  78. /* pfun指向一个函数 */
  79. /* 该函数接受一个Item类型的参数,并无返回值 */
  80. /* 后置条件: pfun指向的这个函数为树中的每一项执行一次 */
  81. void Traverse(const Tree * ptree, void(*pfun)(Item item));
  82.  
  83. /* 操作: 删除树中的所有内容 */
  84. /* 前提条件: ptree指向一个已初始化的树 */
  85. /* 后置条件: 树为空 */
  86. void DeleteAll(Tree * ptree);
  87.  
  88. #endif

tree.c

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "tree.h"
  5.  
  6. /* 局部数据类型 */
  7. typedef struct pair {
  8. Trnode * parent;
  9. Trnode * child;
  10. } Pair;
  11.  
  12. /* 局部函数 */
  13.  
  14. /* 处理动态内存分配和初始化节点 */
  15. static Trnode * MakeNode(const Item * pi);
  16. /* 添加新节点 */
  17. static void AddNode(Trnode * new_node, Trnode * root);
  18. /* 是否应该将新节点添加到左边 */
  19. static bool ToLeft(const Item * i1, const Item *i2);
  20. /* 是否应该将新节点添加到右边 */
  21. static bool ToRight(const Item * i1, const Item *i2);
  22. /* 定位pi节点应放在树中的位置 */
  23. static Pair SeekItem(const Item * pi, const Tree * ptree);
  24. /* 删除指定节点 */
  25. static void DeleteNode(Trnode **ptr);
  26. /* 遍历树 */
  27. static void InOrder(const Trnode * root, void(*pfun)(Item item));
  28. /* 删除所有节点 */
  29. static void DeleteAllNodes(Trnode * root);
  30.  
  31. /* 函数定义 */
  32.  
  33. void InitializeTree(Tree * ptree)
  34. {
  35. ptree->root = NULL;
  36. ptree->size = 0;
  37. }
  38.  
  39. bool TreeIsEmpty(const Tree * ptree)
  40. {
  41. if (ptree->root == NULL)
  42. return true;
  43. else
  44. return false;
  45. }
  46.  
  47. bool TreeIsFull(const Tree * ptree)
  48. {
  49. if (ptree->size == MAXITEMS)
  50. return true;
  51. else
  52. return false;
  53. }
  54.  
  55. int TreeItemCount(const Tree * ptree)
  56. {
  57. return ptree->size;
  58. }
  59.  
  60. bool AddItem(const Item * pi, Tree * ptree)
  61. {
  62. Trnode * new_node;
  63.  
  64. if (TreeIsFull(ptree))
  65. {
  66. fprintf(stderr, "Tree is full\n");
  67. return false;
  68. }
  69. if (SeekItem(pi, ptree).child != NULL)
  70. {
  71. fprintf(stderr, "Attempted to add duplicate item\n");
  72. return false;
  73. }
  74. new_node = MakeNode(pi);
  75. if (new_node == NULL)
  76. {
  77. fprintf(stderr, "Couldn't create node\n");
  78. return false;
  79. }
  80. /* 成功创建了一个新节点 */
  81. ptree->size++;
  82.  
  83. if (ptree->root == NULL) /* 情况1:树为空 */
  84. ptree->root = new_node;
  85. else
  86. AddNode(new_node, ptree->root);
  87.  
  88. return true;
  89. }
  90.  
  91. bool InTree(const Item * pi, const Tree * ptree)
  92. {
  93. return (SeekItem(pi, ptree).child == NULL) ? false : true;
  94. }
  95.  
  96. bool DeleteItem(const Item * pi, Tree * ptree)
  97. {
  98. Pair look;
  99.  
  100. look = SeekItem(pi, ptree);
  101. if (look.child == NULL)
  102. return false;
  103.  
  104. if (look.parent == NULL) /* 删除根节点 */
  105. DeleteNode(&ptree->root);
  106. else if (look.parent->left == look.child)
  107. DeleteNode(&look.parent->left);
  108. else
  109. DeleteNode(&look.parent->right);
  110. ptree->size--;
  111.  
  112. return true;
  113. }
  114.  
  115. void Traverse(const Tree * ptree, void(*pfun)(Item item))
  116. {
  117. if (ptree != NULL)
  118. InOrder(ptree->root, pfun);
  119. }
  120.  
  121. void DeleteAll(Tree * ptree)
  122. {
  123. if (ptree != NULL)
  124. DeleteAllNodes(ptree->root);
  125. ptree->root = NULL;
  126. ptree->size = 0;
  127. }
  128.  
  129. static Trnode * MakeNode(const Item * pi)
  130. {
  131. Trnode * new_node;
  132. new_node = (Trnode *)malloc(sizeof(Trnode));
  133. if (new_node != NULL)
  134. {
  135. new_node->item = *pi;
  136. new_node->left = NULL;
  137. new_node->right = NULL;
  138. }
  139. return new_node;
  140. }
  141.  
  142. static void AddNode(Trnode * new_node, Trnode * root)
  143. {
  144. if (ToLeft(&new_node->item, &root->item))
  145. {
  146. if (root->left == NULL)
  147. root->left = new_node;
  148. else
  149. AddNode(new_node, root->left);
  150. }
  151. else if (ToRight(&new_node->item, &root->item))
  152. {
  153. if (root->right == NULL)
  154. root->right = new_node;
  155. else
  156. AddNode(new_node, root->right);
  157. }
  158. else /* 不允许有重复项 */
  159. {
  160. fprintf(stderr, "location error in AddNode()\n");
  161. exit(1);
  162. }
  163. }
  164.  
  165. static bool ToLeft(const Item * i1, const Item *i2)
  166. {
  167. int comp1;
  168. if ((comp1 = strcmp(i1->petname, i2->petname)) < 0)
  169. return true;
  170. else if (comp1 == 0 && strcmp(i1->petkind, i2->petkind) < 0)
  171. return true;
  172. else
  173. return false;
  174. }
  175.  
  176. static bool ToRight(const Item * i1, const Item *i2)
  177. {
  178. int comp1;
  179. if ((comp1 = strcmp(i1->petname, i2->petname)) > 0)
  180. return true;
  181. else if (comp1 == 0 && strcmp(i1->petkind, i2->petkind) > 0)
  182. return true;
  183. else
  184. return false;
  185. }
  186.  
  187. static Pair SeekItem(const Item * pi, const Tree * ptree)
  188. {
  189. Pair look;
  190. look.parent = NULL;
  191. look.child = ptree->root;
  192. if (look.child == NULL)
  193. return look; //ptree是空树
  194. while (look.child != NULL)
  195. {
  196. if (ToLeft(pi, &(look.child->item)))
  197. {
  198. look.parent = look.child;
  199. look.child = look.child->left;
  200. }
  201. else if (ToRight(pi, &(look.child->item)))
  202. {
  203. look.parent = look.child;
  204. look.child = look.child->right;
  205. }
  206. else
  207. /* 如果前两种情况都不满足,则必须是相等的情况 */
  208. /* look.child 目标项的节点*/
  209. break;
  210. }
  211. return look; /* 成功返回 */
  212. }
  213.  
  214. /* ptr 是指向目标节点的父节点指针成员的地址 */
  215. /* *ptr 指向目标节点 */
  216. static void DeleteNode(Trnode **ptr)
  217. {
  218. Trnode * temp;
  219. if ((*ptr)->left == NULL)
  220. {
  221. temp = *ptr;
  222. *ptr = (*ptr)->right;
  223. free(temp);
  224. }
  225. else if ((*ptr)->right == NULL)
  226. {
  227. temp = *ptr;
  228. *ptr = (*ptr)->left;
  229. free(temp);
  230. }
  231. else /* 被删除的节点有两个子节点 */
  232. {
  233. /* 找到重新连接右子树的位置 */
  234. for (temp = (*ptr)->left; temp->right != NULL; temp = temp->right)
  235. continue;
  236. temp->right = (*ptr)->right;
  237. temp = *ptr;
  238. *ptr = (*ptr)->left;
  239. free(temp);
  240. }
  241. }
  242.  
  243. static void InOrder(const Trnode * root, void(*pfun)(Item item))
  244. {
  245. if (root != NULL)
  246. {
  247. InOrder(root->left, pfun);
  248. (*pfun)(root->item);
  249. InOrder(root->right, pfun);
  250. }
  251. }
  252.  
  253. static void DeleteAllNodes(Trnode * root)
  254. {
  255. Trnode * pright;
  256. if (root != NULL)
  257. {
  258. pright = root->right;
  259. DeleteAllNodes(root->left);
  260. free(root);
  261. DeleteAllNodes(pright);
  262. }
  263. }

main.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. //可以用#ifndef指令,防止多次包含一个文件
  3. #include <stdio.h>
  4. //提供malloc()、rand()、srand()原型
  5. #include <stdlib.h>
  6. #include <time.h>
  7. //提供strcpy()原型
  8. #include <string.h>
  9. //提供CHAR_BIT的定义,CHAR_BIT表示每字节的位数
  10. #include <limits.h>
  11. //C99定义了bool、true、false
  12. //如果编译器不支持bool,可以用枚举替代enum bool {false, true};
  13. #include <stdbool.h>
  14. #include <ctype.h>
  15. #include "tree.h"
  16.  
  17. char menu(void);
  18. void addpet(Tree * pt);
  19. void droppet(Tree * pt);
  20. void showpets(const Tree * pt);
  21. void findpet(const Tree * pt);
  22. void printitem(Item item);
  23. void uppercase(char * str);
  24. char* s_gets(char* st, int n);
  25.  
  26. int main(int argc, char* argv[])
  27. {
  28. Tree pets;
  29. char choice;
  30.  
  31. InitializeTree(&pets);
  32. while ((choice = menu()) != 'q')
  33. {
  34. switch (choice)
  35. {
  36. case 'a': addpet(&pets); break;
  37. case 'l': showpets(&pets); break;
  38. case 'f': findpet(&pets); break;
  39. case 'n':
  40. printf("%d pets in club\n", TreeItemCount(&pets));
  41. break;
  42. case 'd': droppet(&pets); break;
  43. default: puts("Switching error");
  44. }
  45. }
  46. DeleteAll(&pets);
  47. puts("Bye.");
  48.  
  49. system("pause");
  50. return 0;
  51. }
  52.  
  53. char menu(void)
  54. {
  55. int ch;
  56.  
  57. puts("Nerfville Pet Club Membership Program");
  58. puts("Enter the letter corresponding to your choice:");
  59. puts("a) add a pet l) show list of pets");
  60. puts("n) number of pets f) find pets");
  61. puts("d) delete a pet q) quit");
  62. while ((ch = getchar()) != EOF)
  63. {
  64. while (getchar() != '\n') //处理输入行剩余内容
  65. continue;
  66. ch = tolower(ch);
  67. if (strchr("alrfndq", ch) == NULL)
  68. puts("Please enter an a, l, f, n, d, or q:");
  69. else
  70. break;
  71. }
  72. if (ch == EOF)
  73. ch = 'q';
  74.  
  75. return ch;
  76. }
  77.  
  78. void addpet(Tree * pt)
  79. {
  80. Item temp;
  81.  
  82. if (TreeIsFull(pt))
  83. puts("No room in the club!");
  84. else
  85. {
  86. puts("Please enter name of pet:");
  87. s_gets(temp.petname, SLEN);
  88. puts("Please enter pet kind:");
  89. s_gets(temp.petkind, SLEN);
  90. uppercase(temp.petname);
  91. uppercase(temp.petkind);
  92. AddItem(&temp, pt);
  93. }
  94. }
  95.  
  96. void droppet(Tree * pt)
  97. {
  98. Item temp;
  99.  
  100. if (TreeIsEmpty(pt))
  101. {
  102. puts("No entries!");
  103. return;
  104. }
  105. puts("Please enter name of pet you wish to delete:");
  106. s_gets(temp.petname, SLEN);
  107. puts("Please enter pet kind:");
  108. s_gets(temp.petkind, SLEN);
  109. uppercase(temp.petname);
  110. uppercase(temp.petkind);
  111. printf("%s the %s ", temp.petname, temp.petkind);
  112. if (DeleteItem(&temp, pt))
  113. printf("is dropped from the club.\n");
  114. else
  115. printf("is not a member.\n");
  116. }
  117.  
  118. void showpets(const Tree * pt)
  119. {
  120. if (TreeIsEmpty(pt))
  121. puts("No entries!");
  122. else
  123. Traverse(pt, printitem);
  124. }
  125.  
  126. void findpet(const Tree * pt)
  127. {
  128. Item temp;
  129.  
  130. if (TreeIsEmpty(pt))
  131. {
  132. puts("No entries!");
  133. return;
  134. }
  135.  
  136. puts("Please enter name of pet you wish to find:");
  137. s_gets(temp.petname, SLEN);
  138. puts("Please enter pet kind:");
  139. s_gets(temp.petkind, SLEN);
  140. uppercase(temp.petname);
  141. uppercase(temp.petkind);
  142. printf("%s the %s ", temp.petname, temp.petkind);
  143. if (InTree(&temp, pt))
  144. printf("is a member.\n");
  145. else
  146. printf(" is not a member.\n");
  147. }
  148.  
  149. void printitem(Item item)
  150. {
  151. printf("Pet: %-19s Kind: %-19s\n", item.petname, item.petkind);
  152. }
  153.  
  154. void uppercase(char * str)
  155. {
  156. while (*str)
  157. {
  158. *str = toupper(*str);
  159. str++;
  160. }
  161. }
  162.  
  163. // 自己实现读取函数
  164. char* s_gets(char* st, int n)
  165. {
  166. char* ret_val;
  167. int i = 0;
  168. ret_val = fgets(st, n, stdin);
  169. if (ret_val) //即,ret_val != NULL
  170. {
  171. while (st[i] != '\n' && st[i] != '\0')
  172. i++;
  173. if (st[i] == '\n')
  174. st[i] = '\0';
  175. else
  176. while (getchar() != '\n')
  177. continue;
  178. }
  179. return ret_val;
  180. }

运行测试

111.png

标签: C语言

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号