鱼C论坛

 找回密码
 立即注册
查看: 2579|回复: 0

[学习笔记] 抽象数据类型之二叉搜索树ADT接口包

[复制链接]
发表于 2016-9-6 01:04:28 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 mingcxx 于 2016-9-6 01:05 编辑

这份二叉搜索树的接口有几个重要的函数是用递归实现的,譬如AddNode(), InOrder()等等,所以内存开销应该比其他算法要大了些。(算法接下来才学
  1. /*tree.h -- 二叉搜索树的接口头文件*/
  2. /*树中不允许有相同的项目*/
  3. #ifndef _TREE_H_
  4. #define _TREE_H_
  5. #include <stdbool.h>

  6. /*您可以在这里把Item定义为适合的类型*/
  7. typedef struct item
  8. {
  9.         char petname[20];
  10.         char petkind[20];
  11. } Item;

  12. #define MAXITEMS 10

  13. typedef struct node
  14. {
  15.         Item item;
  16.         struct node * left;                /*指向左分支的指针*/
  17.         struct node * right;        /*指向右分支的指针*/
  18. } Node;


  19. typedef struct tree
  20. {
  21.         Node * root;                        /*指向树根的指针*/
  22.         int size;                                /*树中项目的个数*/
  23. } Tree;

  24. /*函数原型*/

  25. /*操作:  把一个树初始化为一个空树*/
  26. /*操作前:ptree指向一个树*/
  27. /*操作后:该树已被初始化为空树*/
  28. void InitializeTree(Tree * ptree);

  29. /*操作:  确定树是否为空*/
  30. /*操作前:ptree指向一个树*/
  31. /*操作后:如果树为空则函数返回tree,
  32.                   否则返回false*/
  33. bool TreeIsEmpty(const Tree * ptree);

  34. /*操作:  确定树是否已满*/
  35. /*操作前:ptree指向一个树*/
  36. /*操作后:如果树已满则函数返回tree,
  37.                   否则返回false*/
  38. bool TreeIsFull(const Tree * ptree);

  39. /*操作:  确定树中项目的个数*/
  40. /*操作前:ptree指向一个树*/
  41. /*操作后:函数返回树中项目的个数*/
  42. int TreeItemCount(const Tree * ptree);

  43. /*操作:  向树中添加一个项目*/
  44. /*操作前:pi是待添加项目的地址
  45.                   ptree指向一个已初始化的树*/
  46. /*操作后:如果可能,函数把项目添加到树中
  47.                   并返回tree,否则返回false*/
  48. bool AddItem(const Item * pi, Tree * ptree);

  49. /*操作:  在树中查找一个项目*/
  50. /*操作前:pi指向一个项目,
  51.                   ptree指向一个已初始化的树*/
  52. /*操作后:如果项目在树中,则函数返回tree,
  53.                   否则返回false*/
  54. bool InTree(const Item * pi, const Tree * ptree);

  55. /*操作:  从树中删除一个项目*/
  56. /*操作前:pi是待删除项目的地址
  57.                   ptree指向一个已初始化的树*/
  58. /*操作后:如果可能,函数从树中删除该项目
  59.                   并返回tree,否则返回false*/
  60. bool DeleteItem(const Item * pi, Tree * ptree);

  61. /*操作:  把一个函数作用于树中每一个项目*/
  62. /*操作前:ptree指向一棵树,
  63.                   pfun指向一个没有返回值的函数,
  64.                   该函数接受一个Item作为参数*/
  65. /*操作后:pfun指向的函数被作用于树中
  66.                   每一个项目一次*/
  67. void Traverse(const Tree * ptree, void(*pfun)(Item item));

  68. /*操作:  从树中删除所有节点*/
  69. /*操作前:ptree指向一个已初始化的树*/
  70. /*操作后:该树为空树*/
  71. void EmptyAll(Tree * ptree);


  72. #endif // !_TREE_H_
复制代码
  1. //tree.c -- 二叉搜索树类型的实现接口

  2. #include <stdio.h>
  3. #include <stdlib.h>                                                        //malloc(), free()
  4. #include <stdbool.h>
  5. #include <string.h>                                                //strcmp()
  6. #include "tree.h"

  7. //局部数据类型
  8. typedef struct pair
  9. {
  10.         Node * parent;
  11.         Node * child;
  12. } Pair;

  13. //局部函数原型
  14. static Node * MakeNode(const Item * pi);
  15. static bool ToLeft(const Item * pi1, const Item * pi2);
  16. static bool ToRight(const Item * pi1, const Item * pi2);
  17. static void AddNode(Node * pnew_node, Node * root);
  18. static void InOrder(const Node * root, void(*pfun)(Item item));
  19. static Pair SeekItem(const Item * pi, const Tree * ptree);
  20. static void DeleteNode(Node ** ptr);
  21. static void DeleteAllNodes(Node * root);


  22. //函数定义
  23. void InitializeTree(Tree * ptree)
  24. {
  25.         ptree->root = NULL;
  26.         ptree->size = 0;
  27. }

  28. bool TreeIsEmpty(const Tree * ptree)
  29. {
  30.         if (ptree->root == NULL)
  31.         {
  32.                 return true;
  33.         }
  34.         else
  35.         {
  36.                 return false;
  37.         }
  38. }

  39. bool TreeIsFull(const Tree * ptree)
  40. {
  41.         if (ptree->size == MAXITEMS)
  42.         {
  43.                 return true;
  44.         }
  45.         else
  46.         {
  47.                 return false;
  48.         }
  49. }

  50. int TreeItemCount(const Tree * ptree)
  51. {
  52.         return ptree->size;
  53. }

  54. bool AddItem(const Item * pi, Tree * ptree)
  55. {
  56.         Node  * pnew_node;

  57.         //检查树是否已满
  58.         if (TreeIsFull(ptree))
  59.         {
  60.                 fprintf(stderr, "Tree is full.\n");
  61.                 return false;
  62.         }
  63.         //检查欲添加项是否已存在
  64.         if (SeekItem(pi, ptree).child != NULL)
  65.         {
  66.                 fprintf(stderr, "Attempted to add duplicate item.\n");
  67.                 return false;
  68.         }

  69.         //尝试创建新节点
  70.         pnew_node = MakeNode(pi);
  71.         if (pnew_node == NULL)
  72.         {
  73.                 fprintf(stderr, "Couldn't create node.\n");
  74.                 return false;
  75.         }
  76.         //创建成功,更新树结构
  77.         ptree->size++;
  78.         if (ptree->root == NULL)
  79.         {
  80.                 ptree->root = pnew_node;
  81.         }
  82.         else
  83.         {
  84.                 AddNode(pnew_node, ptree->root);
  85.         }       
  86.         return true;
  87. }

  88. bool InTree(const Item * pi, const Tree * ptree)
  89. {
  90.         return SeekItem(pi, ptree).child == NULL ? false : true;
  91. }

  92. bool DeleteItem(const Item * pi, Tree * ptree)
  93. {
  94.         Pair look;

  95.         look = SeekItem(pi, ptree);
  96.         if (look.child == NULL)
  97.         {
  98.                 return false;                //失败返回
  99.         }

  100.         if (look.parent == NULL)
  101.         {
  102.                 DeleteNode(&ptree->root);
  103.         }
  104.         else if (look.parent->left == look.child)
  105.         {
  106.                 DeleteNode(&look.parent->left);
  107.         }
  108.         else
  109.         {
  110.                 DeleteNode(&look.parent->right);
  111.         }
  112.         ptree->size--;
  113.         return true;
  114. }

  115. void Traverse(const Tree * ptree, void(*pfun)(Item item))
  116. {
  117.         if (ptree->root != NULL)
  118.         {
  119.                 InOrder(ptree->root, pfun);
  120.         }
  121. }

  122. void EmptyAll(Tree * ptree)
  123. {
  124.         if (ptree->root != NULL)
  125.         {
  126.                 DeleteAllNodes(ptree->root);
  127.         }
  128.         ptree->root = NULL;
  129.         ptree->size = 0;
  130. }


  131. //局部函数定义

  132. Node * MakeNode(const Item * pi)
  133. {
  134.         Node * pnew_node;

  135.         pnew_node = (Node *)malloc(sizeof(Node));                //分配节点内存
  136.         if (pnew_node != NULL)                                        //分配到时进行节点的初始化
  137.         {
  138.                 pnew_node->item = *pi;
  139.                 pnew_node->left = NULL;
  140.                 pnew_node->right = NULL;
  141.         }
  142.         return pnew_node;
  143. }

  144. bool ToLeft(const Item * pi1, const Item * pi2)
  145. {
  146.         int comp1;

  147.         if ((comp1 = strcmp(pi1->petname, pi2->petname)) < 0)
  148.         {
  149.                 return true;
  150.         }
  151.         else if (comp1 == 0 && strcmp(pi1->petkind, pi2->petkind) < 0)
  152.         {
  153.                 return true;
  154.         }
  155.         else
  156.         {
  157.                 return false;
  158.         }
  159. }

  160. bool ToRight(const Item * pi1, const Item * pi2)
  161. {
  162.         int comp1;

  163.         if ((comp1 = strcmp(pi1->petname, pi2->petname)) > 0)
  164.         {
  165.                 return true;
  166.         }
  167.         else if (comp1 = 0 && strcmp(pi1->petkind, pi2->petkind) > 0)
  168.         {
  169.                 return true;
  170.         }
  171.         else
  172.         {
  173.                 return false;
  174.         }
  175. }

  176. void AddNode(Node * pnew_node, Node * root)                        //递归
  177. {
  178.         if (ToLeft(&pnew_node->item, &root->item))
  179.         {
  180.                 if (root->left == NULL)
  181.                 {
  182.                         root->left = pnew_node;
  183.                 }
  184.                 else
  185.                 {
  186.                         AddNode(pnew_node, root->left);
  187.                 }
  188.         }
  189.         else if (ToRight(&pnew_node->item,&root->item))
  190.         {
  191.                 if (root->right == NULL)
  192.                 {
  193.                         root->right = pnew_node;
  194.                 }
  195.                 else
  196.                 {
  197.                         AddNode(pnew_node, root->right);
  198.                 }
  199.         }
  200.         else
  201.         {
  202.                 fprintf(stderr, "location error in AddNode().\n");
  203.                 exit(EXIT_FAILURE);
  204.         }
  205. }

  206. void InOrder(const Node * root, void(*pfun)(Item item))                //递归
  207. {
  208.         //递归调用访问非空的子树,遍历顺序:中序遍历
  209.         if (root != NULL)
  210.         {
  211.                 InOrder(root->left, pfun);
  212.                 (*pfun)(root->item);
  213.                 InOrder(root->right, pfun);
  214.         }
  215. }

  216. Pair SeekItem(const Item * pi, const Tree * ptree)                //递归
  217. {
  218.         Pair look;

  219.         look.parent = NULL;
  220.         look.child = ptree->root;

  221.         if (look.child == NULL)
  222.         {
  223.                 return look;                                                                                //空树返回
  224.         }
  225.         while (look.child != NULL)
  226.         {
  227.                 if (ToLeft(pi, &look.child->item))
  228.                 {
  229.                         look.parent = look.child;
  230.                         look.child = look.child->left;
  231.                 }
  232.                 else if (ToRight(pi, &look.child->item))
  233.                 {
  234.                         look.parent = look.child;
  235.                         look.child = look.child->right;
  236.                 }
  237.                 else
  238.                 {
  239.                         break;                //如果前两种情况都不满足,必定为相等的情况,中断循环,look.child等于目标节点的地址
  240.                 }
  241.         }
  242.         return look;
  243. }

  244. void DeleteNode(Node ** ptr)
  245. {
  246.         Node * temp;

  247.         puts((*ptr)->item.petname);
  248.         if ((*ptr)->left == NULL)
  249.         {
  250.                 *ptr = (*ptr)->right;        //只有右支时,让待删节点的父节点中指向该节点的指针,修改为指向待删节点的右子树
  251.         }
  252.         else if ((*ptr)->right == NULL)
  253.         {
  254.                 *ptr = (*ptr)->left;        //同上
  255.         }
  256.         else                                //待删节点有2个子节点
  257.         {       
  258.                                                                 //在左子树的右支查找空的右子树
  259.                 for (temp = (*ptr)->left; temp->right == NULL; temp = temp->right)
  260.                 {
  261.                         continue;
  262.                 }
  263.                 temp->right = (*ptr)->right;
  264.                 temp = *ptr;
  265.                 *ptr = temp->left;
  266.                 free(temp);
  267.         }
  268. }

  269. void DeleteAllNodes(Node * root)                                //递归
  270. {
  271.         Node *pright;

  272.         if (root != NULL)
  273.         {
  274.                 //中序遍历删除非空的子树
  275.                 pright = root->right;
  276.                 DeleteAllNodes(root->left);
  277.                 free(root);
  278.                 DeleteAllNodes(pright);
  279.         }
  280. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-16 10:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表