鱼C论坛

 找回密码
 立即注册
查看: 8747|回复: 21

关于平衡二叉树完整算法实现(部分修改)

[复制链接]
发表于 2015-11-11 20:52:47 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 零度非安全 于 2015-12-3 21:30 编辑
哈喽,各位鱼油们你们好,由于最近在忙各种课程作业,所以很少上论坛,今天有幸跟各位鱼油来分享下关于平衡二叉树算法的实现

早在之前,小甲鱼老师已经在《数据结构与算法》中提到了关于平衡二叉树的讲解,当时我也看的稀里糊涂的,完全不知道他在讲什么?但是这个学期我们也在学这门课程,所以呢,我花了几天的时间写了个关于平衡二叉树的算法,个人觉得还算可以,如果有谁看了我写的算法后,觉得某些地方需要改动的话,请跟帖回复


如果有人提出较好的意见的,我会给额外的奖励滴
代码共计478行,代码如下:
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<malloc.h>
  4. #define MaxSize 100
  5. #define MaxWith 50

  6. typedef int KeyType;
  7. typedef char InfoType;

  8. /*定义各节点的类型*/
  9. typedef struct node
  10. {
  11.         KeyType key;                                                                                                                        /*关键字项*/
  12.         int bf;                                                                                                                                        /*增加的平衡因子*/
  13.         InfoType data;                                                                                                                        /*其它的数据与域*/
  14.         struct node *lchild;                                                                                                        /*左孩子指针*/
  15.         struct node *rchild;                                                                                                        /*右孩子指针*/
  16. }AVLNode;                                                                                                                                        /*AVL树中节点类型定义*/

  17. int m = 0;
  18. AVLNode *b = NULL;                                                                                                                        /*定义全局变量m、*b*/

  19. /*左平衡旋转情况处理*/
  20. void LeftProcess(AVLNode *&p, int &taller)
  21. {
  22.         AVLNode *p1, *p2;
  23.         if (p->bf == 0)                                                                                                                        /*当左右子树等高时插入使树高度增加*/
  24.         {
  25.                 p->bf = 1;
  26.                 taller = 1;                                                                                                                        /*所以平衡因子置为1,高度为1*/
  27.         }
  28.         else if (p->bf == -1)                                                                                                        /*当右子树比左子树高,插入后左右子树等高*/
  29.         {
  30.                 p->bf = 0;
  31.                 taller = 0;                                                                                                                        /*所以平衡因子置为0,高度为0*/
  32.         }
  33.         else                                                                                                                                        /*当左子树比右子树高时插入则需做左平衡处理*/
  34.         {
  35.                 p1 = p->lchild;
  36.                 if (p1->bf == 1)                                                                                                        /*当插入到左孩子的左子树上时需做LL处理*/
  37.                 {
  38.                         p->lchild = p1->rchild;
  39.                         p1->rchild = p;
  40.                         p->bf = p1->bf = 0;
  41.                         p = p1;
  42.                 }
  43.                 else if (p1->bf == -1)                                                                                                /*当插入到左孩子的右子树上时需做LR处理*/
  44.                 {
  45.                         p2 = p1->rchild;
  46.                         p1->rchild = p2->lchild;
  47.                         p2->lchild = p1;
  48.                         p->lchild = p2->rchild;
  49.                         p2->rchild = p;
  50.                         p = p2;                                                                                                                        /*将p指向新的根节点,并置bf的值为0*/
  51.                         p->bf = 0;
  52.                 }
  53.                 taller = 0;
  54.         }
  55. }

  56. /*右平衡旋转情况处理*/
  57. void RightProcess(AVLNode *&p, int &taller)                                                                        /*操作类似上面,请参照左平衡旋转处理*/
  58. {
  59.         AVLNode *p1, *p2;
  60.         if (p->bf == 0)
  61.         {
  62.                 p->bf = -1;
  63.                 taller = 1;
  64.         }
  65.         else if (p->bf == 1)
  66.         {
  67.                 p->bf = 0;
  68.                 taller = 0;
  69.         }
  70.         else
  71.         {
  72.                 p1 = p->rchild;
  73.                 if (p1->bf == -1)
  74.                 {
  75.                         p->rchild = p1->lchild;
  76.                         p1->lchild = p;
  77.                         p->bf = p1->bf = 0;
  78.                         p = p1;
  79.                 }
  80.                 else if (p1->bf == 1)
  81.                 {
  82.                         p2 = p1->lchild;
  83.                         p1->lchild = p2->rchild;
  84.                         p2->rchild = p1;
  85.                         p->rchild = p2->lchild;
  86.                         p2->lchild = p;
  87.                         p = p2;
  88.                         p->bf = 0;
  89.                 }
  90.                 taller = 0;
  91.         }
  92. }

  93. /*在进行删除平衡二叉树的节点时候需要做相应的左平衡旋转处理*/
  94. void LeftProcess1(AVLNode *&p, int &taller)
  95. {
  96.         AVLNode *p1, *p2;
  97.         if (p->bf == 1)
  98.         {
  99.                 p->bf = 0;
  100.                 taller = 1;
  101.         }
  102.         else if (p->bf == 0)
  103.         {
  104.                 p->bf = -1;
  105.                 taller = 0;
  106.         }
  107.         else
  108.         {
  109.                 p1 = p->rchild;                                                                                                                /*RR处理*/
  110.                 if (p1->bf == 0)
  111.                 {
  112.                         p->rchild = p1->lchild;
  113.                         p1->rchild = p;
  114.                         p1->bf = 1;
  115.                         p->bf = -1;
  116.                         p = p1;
  117.                         taller = 0;
  118.                 }
  119.                 else if (p1->bf == -1)                                                                                                /*RR处理*/
  120.                 {
  121.                         p->rchild = p1->lchild;
  122.                         p1->lchild = p;
  123.                         p->bf = p1->bf = 0;
  124.                         p = p1;
  125.                         taller = 1;
  126.                 }
  127.                 else                                                                                                                                /*RL处理*/
  128.                 {
  129.                         p2 = p1->lchild;
  130.                         p1->lchild = p2->rchild;
  131.                         p2->rchild = p1;
  132.                         p->rchild = p2->lchild;
  133.                         p2->lchild = p;
  134.                         p2->bf = 0;
  135.                         p = p2;
  136.                         taller = 1;
  137.                 }
  138.         }
  139. }

  140. /*在进行删除平衡二叉树的节点时候需要做相应的右平衡旋转处理*/
  141. void RightProcess1(AVLNode *&p, int &taller)
  142. {
  143.         AVLNode *p1, *p2;
  144.         if (p->bf == -1)
  145.         {
  146.                 p->bf = 0;
  147.                 taller = -1;
  148.         }
  149.         else if (p->bf == 0)
  150.         {
  151.                 p->bf = 1;
  152.                 taller = 0;
  153.         }
  154.         else                                                                                                                                        /*LL处理*/
  155.         {
  156.                 p1 = p->lchild;
  157.                 if (p1->bf == 0)
  158.                 {
  159.                         p->lchild = p1->rchild;
  160.                         p1->rchild = p;
  161.                         p->bf = -1;
  162.                         p1->bf = 1;
  163.                         p = p1;
  164.                         taller = 0;
  165.                 }
  166.                 else if (p1->bf == 1)                                                                                                /*LL处理*/
  167.                 {
  168.                         p->lchild = p1->rchild;
  169.                         p1->rchild = p;
  170.                         p->bf = p1->bf = 0;
  171.                         p = p1;
  172.                         taller = 1;
  173.                 }
  174.                 else                                                                                                                                /*LR处理*/
  175.                 {
  176.                         p2 = p1->rchild = p2->lchild;
  177.                         p2->lchild = p1;
  178.                         p->lchild = p2->rchild;
  179.                         p2->rchild = p;
  180.                         p2->bf = 0;
  181.                         p = p2;
  182.                         taller = 1;
  183.                 }
  184.         }
  185. }

  186. void Delete2(AVLNode *q, AVLNode *&r, int &taller)                                                        /*用于被删除节点左右子树均不为空*/
  187. {
  188.         if (r->rchild == NULL)
  189.         {
  190.                 q->key = r->key;
  191.                 q = r;
  192.                 r = r->lchild;
  193.                 free(q);
  194.                 taller = 1;
  195.         }
  196.         else
  197.         {
  198.                 Delete2(q, r->rchild, taller);
  199.                 if (taller == 1)
  200.                         RightProcess(r, taller);
  201.         }
  202. }

  203. /*删除平衡二叉树的节点*/
  204. int DeleteAVL(AVLNode *&p, KeyType x, int &taller)
  205. {
  206.         int k;
  207.         AVLNode *q;
  208.         if (p == NULL)                                                                                                                        /*如果为空树,则正常退出*/
  209.                 return 0;
  210.         else if (x < p->key)                                                                                                        /*如果待删除的节点小于该节点,则往它左孩子寻找*/
  211.         {
  212.                 k = DeleteAVL(p->lchild, x, taller);
  213.                 if (taller == 1)                                                                                                        /**/
  214.                         LeftProcess(p, taller);
  215.                 return k;
  216.         }
  217.         else if (x > p->key)
  218.         {
  219.                 k = DeleteAVL(p->rchild, x, taller);
  220.                 if (taller == 1)
  221.                         RightProcess1(p, taller);
  222.                 return k;
  223.         }
  224.         else
  225.         {
  226.                 q = p;
  227.                 if (p->rchild == NULL)                                                                                                /*被删节点右子树为空*/
  228.                 {
  229.                         p = p->lchild;
  230.                         free(q);
  231.                         taller = 1;
  232.                 }
  233.                 else if (p->rchild == NULL)                                                                                        /*被删节点左子树为空*/
  234.                 {
  235.                         p = p->lchild;
  236.                         free(q);
  237.                         taller = 1;
  238.                 }
  239.                 else                                                                                                                                /*被删节点左右子树均不为空*/
  240.                 {
  241.                         Delete2(q, q->lchild, taller);
  242.                         if (taller == 1)
  243.                                 LeftProcess1(q, taller);
  244.                         p = q;
  245.                 }
  246.                 return 1;
  247.         }
  248. }

  249. /*销毁平衡二叉树*/
  250. void DestroyAVL(AVLNode *&b)
  251. {
  252.         if (b->lchild)
  253.                 DestroyAVL(b->lchild);
  254.         if (b->rchild)
  255.                 DestroyAVL(b->rchild);
  256.         free(b);
  257.         b = NULL;
  258. }

  259. /*向当前平衡二叉树插入一个元素*/
  260. int InsertNode(AVLNode *&b, KeyType e, int &taller)
  261. {
  262.         if (b == NULL)                                                                                                                        /*当b为空树时进行动态分配等待插入新元素*/
  263.         {
  264.                 b = (AVLNode *)malloc(sizeof(AVLNode));
  265.                 b->key = e;
  266.                 b->lchild = b->rchild = NULL;
  267.                 b->bf = 0;                                                                                                                        /*将平衡因子置为 0*/
  268.                 taller = 1;                                                                                                                        /*将该节点的高度置为 1*/
  269.         }
  270.         else
  271.         {
  272.                 if (e == b->key)                                                                                                        /*如果树中已经存在该点,则无需插入*/
  273.                 {
  274.                         taller = 0;
  275.                         return 0;
  276.                 }
  277.                 if (e < b->key)                                                                                                                /*如果待插入的数小于该节点,则往它左孩子插入*/
  278.                 {
  279.                         if ((InsertNode(b->lchild, e, taller)) == 0)
  280.                                 return 0;
  281.                         if (taller == 1)                                                                                                /*若该节点的高度为1,插入后增1,则会破坏平衡*/
  282.                                 LeftProcess(b, taller);                                                                                /*破坏后进行左平衡旋转处理重新达到平衡*/
  283.                 }
  284.                 else                                                                                                                                /*否则往它右孩子插入*/
  285.                 {
  286.                         if ((InsertNode(b->rchild, e, taller)) == 0)
  287.                                 return 0;
  288.                         if (taller == 1)                                                                                                /*若该节点的高度为1,插入后增1,则会破坏平衡*/
  289.                                 RightProcess(b, taller);                                                                        /*破坏后进行右平衡旋转处理重新达到平衡*/
  290.                 }
  291.         }
  292.         return 1;
  293. }

  294. /*输出要选择操作的功能菜单*/
  295. void OutputAVL(AVLNode *b)
  296. {
  297.         system("cls");
  298.         system("color a");
  299.         printf("\t\t******************************************\n");
  300.         printf("\t\t*             平衡二叉树操作             *\n");
  301.         printf("\t\t*        ==请 选 择 你 的 操 作==        *\n");
  302.         printf("\t\t*                                        *\n");
  303.         printf("\t\t*           A.创          建             *\n");
  304.         printf("\t\t*           B.显          示             *\n");
  305.         printf("\t\t*           C.查          找             *\n");
  306.         printf("\t\t*           D.插          入             *\n");
  307.         printf("\t\t*           E.删          除             *\n");
  308.         printf("\t\t*           F.销          毁             *\n");
  309.         printf("\t\t*           G.退          出             *\n");
  310.         printf("\t\t*                                        *\n");
  311.         printf("\t\t*     爱鱼C、爱编程、爱世界、爱和平      *\n");
  312.         printf("\t\t*           www.bbs.fishc.com            *\n");
  313.         printf("\t\t*                      ---By:零度非安全  *\n");
  314.         printf("\t\t******************************************\n");
  315. }

  316. /*递归查找平衡二叉树中的元素*/
  317. bool SearchAVLNode(AVLNode *&b, int n)
  318. {
  319.         if (!b)
  320.                 return false;
  321.         else if (n == b->key)                                                                                                /*找到了返回true*/
  322.                 return true;
  323.         else if (n < b->key)
  324.                 return SearchAVLNode(b->lchild, n);                                                                /*如果小于则继续在其左孩子中查找*/
  325.         else
  326.                 return SearchAVLNode(b->rchild, n);                                                                /*否则就到右孩子中查找*/
  327. }

  328. /*打印平衡二叉树的状态*/
  329. void PrintAVLNode(AVLNode *b)
  330. {
  331.         AVLNode *p, *St[MaxSize];
  332.         int level[MaxSize][2], top, n, i, width = 4;
  333.         if (b != NULL)
  334.         {
  335.                 top = 1;
  336.                 St[top] = b;                                                                                                        /*将根节点入栈*/
  337.                 level[top][0] = width;
  338.                 while (top > 0)
  339.                 {
  340.                         p = St[top];
  341.                         n = level[top][0];
  342.                         for (i = 1; i <= n; i++)
  343.                                 printf(" ");
  344.                         printf("%d", p->key);
  345.                         for (i = n + 1; i < MaxSize - 6; i += 2)
  346.                                 printf("*");
  347.                         printf("\n");
  348.                         top--;
  349.                         if (p->rchild != NULL)                                                                                /*将右孩子根节点入栈*/
  350.                         {
  351.                                 top++;
  352.                                 St[top] = p->rchild;
  353.                                 level[top][0] = n + width;
  354.                         }
  355.                         if (p->lchild != NULL)                                                                                /*将左孩子根节点入栈*/
  356.                         {
  357.                                 top++;
  358.                                 St[top] = p->lchild;
  359.                                 level[top][0] = n + width;
  360.                         }
  361.                 }
  362.         }
  363. }

  364. /*创建一个平衡二叉树*/
  365. AVLNode *CreateAVL(AVLNode *&b)
  366. {
  367.         int mainkey, i;
  368.         b = NULL;
  369.         printf("请输入节点(以-1结束):");
  370.         scanf("%d", &mainkey);
  371.         while (mainkey != -1)                                                                                                /*当输入的数不为-1时进行循环*/
  372.         {
  373.                 InsertNode(b, mainkey, i);
  374.                 printf("当前二叉树状态:\n");
  375.                 PrintAVLNode(b);
  376.                 printf("请输入节点(以-1结束):");
  377.                 scanf("%d", &mainkey);
  378.         }
  379.         return b;
  380. }

  381. /*主函数*/
  382. int main()
  383. {
  384.         int node, h;
  385.         char ch;                                                                                                                        /*定义一个输入变量*/
  386.         while (1)                                                                                                                        /*进行循环操作*/
  387.         {
  388.                 OutputAVL(b);
  389.                 printf("请选择:");
  390.                 ch = getchar();
  391.                 fflush(stdin);                                                                                                        /*清除输入的缓存*/
  392.                 if (ch == 'A')                                                                                                        /*进行创建操作*/
  393.                 {
  394.                         system("cls");
  395.                         printf("正在创建中......\n\n");
  396.                         CreateAVL(b);
  397.                         system("pause");
  398.                 }
  399.                 else if (ch == 'B')                                                                                                /*进行显示操作*/
  400.                 {
  401.                         system("cls");
  402.                         printf("当前平衡二叉树的状态为:\n");
  403.                         PrintAVLNode(b);
  404.                         system("pause");
  405.                 }
  406.                 else if (ch == 'C')                                                                                                /*进行查找操作*/
  407.                 {
  408.                         system("cls");
  409.                         printf("正在查找中......\n\n");
  410.                         printf("请输入要查找的关键字:\n");
  411.                         scanf("%d", &node);
  412.                         if (SearchAVLNode(b, node))
  413.                         {
  414.                                 printf("查找成功!\n");
  415.                                 PrintAVLNode(b);                                                                                /*当查找成功时输出当前平衡二叉树的状态*/
  416.                         }
  417.                         else
  418.                         {
  419.                                 printf("查找失败!\n");
  420.                                 printf("当前平衡二叉树中根本不存在这个节点\n");                        /*当查找失败提示用户这树中不存在该节点*/
  421.                         }
  422.                         system("pause");
  423.                 }
  424.                 else if (ch == 'D')                                                                                                /*进行插入操作*/
  425.                 {
  426.                         system("cls");
  427.                         printf("正在插入中......\n\n");
  428.                         printf("请输入关键字(整数):\n");
  429.                         scanf("%d", &node);
  430.                         InsertNode(b, node, h);
  431.                         system("pause");
  432.                 }
  433.                 else if (ch == 'E')                                                                                                /*进行删除操作*/
  434.                 {
  435.                         system("cls");
  436.                         printf("正在删除中......\n\n");
  437.                         printf("请输入关键字(整数):\n");
  438.                         scanf("%d", &node);
  439.                         if (DeleteAVL(b, node, h))
  440.                         {
  441.                                 printf("删除成功!\n");
  442.                                 PrintAVLNode(b);                                                                                /*当删除成功时及时显示当前平衡二叉树状态*/
  443.                         }
  444.                         else
  445.                                 printf("删除失败!\n");
  446.                         system("pause");
  447.                 }
  448.                 else if (ch == 'F')                                                                                                /*进行销毁操作*/
  449.                 {
  450.                         system("cls");
  451.                         printf("正在销毁中......\n\n");
  452.                         DestroyAVL(b);
  453.                         printf("销毁成功!\n");
  454.                         system("pause");
  455.                 }
  456.                 else if (ch == 'G')                                                                                                /*进行退出操作*/
  457.                         exit(0);
  458.                 OutputAVL(b);
  459.                 fflush(stdin);
  460.         }
  461.         return 0;                                                                                                                        /*程序正常退出*/
  462. }
复制代码

源码文件: 平衡二叉树源码文件.rar (9.05 KB, 下载次数: 42)



程序文件: 平衡二叉树演示.rar (17.2 KB, 下载次数: 23)

0.png


1.png


2.png


3.png


4.png


5.png



评分

参与人数 1荣誉 +10 鱼币 +10 贡献 +10 收起 理由
康小泡 + 10 + 10 + 10 支持楼主!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2015-11-17 19:22:53 | 显示全部楼层

回帖奖励 +5 鱼币

挺厉害啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-11-17 20:48:42 | 显示全部楼层

谢谢泡泡姐
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-19 09:55:19 From FishC Mobile | 显示全部楼层

回帖奖励 +5 鱼币

我还没学到,看不懂?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-19 21:15:49 | 显示全部楼层

回帖奖励 +5 鱼币

有点看不懂。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-20 02:34:11 | 显示全部楼层

回帖奖励 +5 鱼币

哈哈,看来还要想办法改进下课程~~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-20 08:36:29 | 显示全部楼层

回帖奖励 +5 鱼币

这是啥
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-20 09:14:23 | 显示全部楼层

回帖奖励 +5 鱼币

真厉害,不错哦。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-21 20:41:15 | 显示全部楼层

回帖奖励 +5 鱼币

人工置顶
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-24 16:47:02 | 显示全部楼层

回帖奖励 +5 鱼币

感谢分享
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-24 17:23:39 | 显示全部楼层

回帖奖励 +5 鱼币

厉害!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2015-11-24 20:42:28 | 显示全部楼层

回帖奖励 +5 鱼币

我们也开了这门课,,可似乎我们没有讲到平衡为二叉树!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-24 22:05:28 | 显示全部楼层

回帖奖励 +5 鱼币

挺好的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-26 11:30:39 | 显示全部楼层

回帖奖励 +5 鱼币

过来看看  呵呵
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-26 11:31:11 | 显示全部楼层
真棒   天才啊  呵呵
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-26 14:16:23 | 显示全部楼层

回帖奖励 +5 鱼币

我的妈来,真厉害
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-26 14:16:54 | 显示全部楼层
话说,代码这么长。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-11-30 19:28:25 | 显示全部楼层

回帖奖励 +5 鱼币

在吗
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-12-1 12:37:51 | 显示全部楼层

???   我在的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-1 13:58:58 | 显示全部楼层

回帖奖励 +5 鱼币

学习~
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-19 19:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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