【第十四周项目1 - 验证算法之平衡二叉树】

问题及代码:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * Copyright (c) 2016, 烟台大学计算机与控制工程学院 
  3.  * All rights reserved. 
  4.  * 文件名称:Cube007.cpp 
  5.  * 作    者:杨俊杰
  6.  * 完成日期:2016年12月8日 
  7.  * 
  8.  * 问题描述:验证平衡二叉树相关算法 
  9.  * 输入描述:无 
  10.  * 输出描述:结果 
  11.  */  
  12.   
  13. #include <stdio.h>  
  14. #include <malloc.h>  
  15. typedef int KeyType;                    //定义关键字类型  
  16. typedef char InfoType;  
  17. typedef struct node                     //记录类型  
  18. {  
  19.     KeyType key;                        //关键字项  
  20.     int bf;                             //平衡因子  
  21.     InfoType data;                      //其他数据域  
  22.     struct node *lchild,*rchild;        //左右孩子指针  
  23. } BSTNode;  
  24. void LeftProcess(BSTNode *&p,int &taller)  
  25. //对以指针p所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针p指向新的根结点  
  26. {  
  27.     BSTNode *p1,*p2;  
  28.     if (p->bf==0)           //原本左、右子树等高,现因左子树增高而使树增高  
  29.     {  
  30.         p->bf=1;  
  31.         taller=1;  
  32.     }  
  33.     else if (p->bf==-1)     //原本右子树比左子树高,现左、右子树等高  
  34.     {  
  35.         p->bf=0;  
  36.         taller=0;  
  37.     }  
  38.     else                    //原本左子树比右子树高,需作左子树的平衡处理  
  39.     {  
  40.         p1=p->lchild;       //p指向*p的左子树根结点  
  41.         if (p1->bf==1)      //新结点插入在*b的左孩子的左子树上,要作LL调整  
  42.         {  
  43.             p->lchild=p1->rchild;  
  44.             p1->rchild=p;  
  45.             p->bf=p1->bf=0;  
  46.             p=p1;  
  47.         }  
  48.         else if (p1->bf==-1)    //新结点插入在*b的左孩子的右子树上,要作LR调整  
  49.         {  
  50.             p2=p1->rchild;  
  51.             p1->rchild=p2->lchild;  
  52.             p2->lchild=p1;  
  53.             p->lchild=p2->rchild;  
  54.             p2->rchild=p;  
  55.             if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况  
  56.                 p->bf=p1->bf=0;  
  57.             else if (p2->bf==1)     //新结点插在*p2的左子树上的情况  
  58.             {  
  59.                 p1->bf=0;  
  60.                 p->bf=-1;  
  61.             }  
  62.             else                    //新结点插在*p2的右子树上的情况  
  63.             {  
  64.                 p1->bf=1;  
  65.                 p->bf=0;  
  66.             }  
  67.             p=p2;  
  68.             p->bf=0;            //仍将p指向新的根结点,并置其bf值为0  
  69.         }  
  70.         taller=0;  
  71.     }  
  72. }  
  73. void RightProcess(BSTNode *&p,int &taller)  
  74. //对以指针p所指结点为根的二叉树作右平衡旋转处理,本算法结束时,指针p指向新的根结点  
  75. {  
  76.     BSTNode *p1,*p2;  
  77.     if (p->bf==0)           //原本左、右子树等高,现因右子树增高而使树增高  
  78.     {  
  79.         p->bf=-1;  
  80.         taller=1;  
  81.     }  
  82.     else if (p->bf==1)      //原本左子树比右子树高,现左、右子树等高  
  83.     {  
  84.         p->bf=0;  
  85.         taller=0;  
  86.     }  
  87.     else                    //原本右子树比左子树高,需作右子树的平衡处理  
  88.     {  
  89.         p1=p->rchild;       //p指向*p的右子树根结点  
  90.         if (p1->bf==-1)     //新结点插入在*b的右孩子的右子树上,要作RR调整  
  91.         {  
  92.             p->rchild=p1->lchild;  
  93.             p1->lchild=p;  
  94.             p->bf=p1->bf=0;  
  95.             p=p1;  
  96.         }  
  97.         else if (p1->bf==1) //新结点插入在*p的右孩子的左子树上,要作RL调整  
  98.         {  
  99.             p2=p1->lchild;  
  100.             p1->lchild=p2->rchild;  
  101.             p2->rchild=p1;  
  102.             p->rchild=p2->lchild;  
  103.             p2->lchild=p;  
  104.             if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况  
  105.                 p->bf=p1->bf=0;  
  106.             else if (p2->bf==-1)    //新结点插在*p2的右子树上的情况  
  107.             {  
  108.                 p1->bf=0;  
  109.                 p->bf=1;  
  110.             }  
  111.             else                    //新结点插在*p2的左子树上的情况  
  112.             {  
  113.                 p1->bf=-1;  
  114.                 p->bf=0;  
  115.             }  
  116.             p=p2;  
  117.             p->bf=0;            //仍将p指向新的根结点,并置其bf值为0  
  118.         }  
  119.         taller=0;  
  120.     }  
  121. }  
  122. int InsertAVL(BSTNode *&b,KeyType e,int &taller)  
  123. /*若在平衡的二叉排序树b中不存在和e有相同关键字的结点,则插入一个 
  124.   数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树 
  125.   失去平衡,则作平衡旋转处理,布尔变量taller反映b长高与否*/  
  126. {  
  127.     if(b==NULL)         //原为空树,插入新结点,树“长高”,置taller为1  
  128.     {  
  129.         b=(BSTNode *)malloc(sizeof(BSTNode));  
  130.         b->key=e;  
  131.         b->lchild=b->rchild=NULL;  
  132.         b->bf=0;  
  133.         taller=1;  
  134.     }  
  135.     else  
  136.     {  
  137.         if (e==b->key)              //树中已存在和e有相同关键字的结点则不再插入  
  138.         {  
  139.             taller=0;  
  140.             return 0;  
  141.         }  
  142.         if (e<b->key)               //应继续在*b的左子树中进行搜索  
  143.         {  
  144.             if ((InsertAVL(b->lchild,e,taller))==0) //未插入  
  145.                 return 0;  
  146.             if (taller==1)          //已插入到*b的左子树中且左子树“长高”  
  147.                 LeftProcess(b,taller);  
  148.         }  
  149.         else                        //应继续在*b的右子树中进行搜索  
  150.         {  
  151.             if ((InsertAVL(b->rchild,e,taller))==0) //未插入  
  152.                 return 0;  
  153.             if (taller==1)          //已插入到b的右子树且右子树“长高”  
  154.                 RightProcess(b,taller);  
  155.         }  
  156.     }  
  157.     return 1;  
  158. }  
  159. void DispBSTree(BSTNode *b) //以括号表示法输出AVL  
  160. {  
  161.     if (b!=NULL)  
  162.     {  
  163.         printf("%d",b->key);  
  164.         if (b->lchild!=NULL || b->rchild!=NULL)  
  165.         {  
  166.             printf("(");  
  167.             DispBSTree(b->lchild);  
  168.             if (b->rchild!=NULL) printf(",");  
  169.             DispBSTree(b->rchild);  
  170.             printf(")");  
  171.         }  
  172.     }  
  173. }  
  174. void LeftProcess1(BSTNode *&p,int &taller)  //在删除结点时进行左处理  
  175. {  
  176.     BSTNode *p1,*p2;  
  177.     if (p->bf==1)  
  178.     {  
  179.         p->bf=0;  
  180.         taller=1;  
  181.     }  
  182.     else if (p->bf==0)  
  183.     {  
  184.         p->bf=-1;  
  185.         taller=0;  
  186.     }  
  187.     else        //p->bf=-1  
  188.     {  
  189.         p1=p->rchild;  
  190.         if (p1->bf==0)          //需作RR调整  
  191.         {  
  192.             p->rchild=p1->lchild;  
  193.             p1->lchild=p;  
  194.             p1->bf=1;  
  195.             p->bf=-1;  
  196.             p=p1;  
  197.             taller=0;  
  198.         }  
  199.         else if (p1->bf==-1)    //需作RR调整  
  200.         {  
  201.             p->rchild=p1->lchild;  
  202.             p1->lchild=p;  
  203.             p->bf=p1->bf=0;  
  204.             p=p1;  
  205.             taller=1;  
  206.         }  
  207.         else                    //需作RL调整  
  208.         {  
  209.             p2=p1->lchild;  
  210.             p1->lchild=p2->rchild;  
  211.             p2->rchild=p1;  
  212.             p->rchild=p2->lchild;  
  213.             p2->lchild=p;  
  214.             if (p2->bf==0)  
  215.             {  
  216.                 p->bf=0;  
  217.                 p1->bf=0;  
  218.             }  
  219.             else if (p2->bf==-1)  
  220.             {  
  221.                 p->bf=1;  
  222.                 p1->bf=0;  
  223.             }  
  224.             else  
  225.             {  
  226.                 p->bf=0;  
  227.                 p1->bf=-1;  
  228.             }  
  229.             p2->bf=0;  
  230.             p=p2;  
  231.             taller=1;  
  232.         }  
  233.     }  
  234. }  
  235. void RightProcess1(BSTNode *&p,int &taller) //在删除结点时进行右处理  
  236. {  
  237.     BSTNode *p1,*p2;  
  238.     if (p->bf==-1)  
  239.     {  
  240.         p->bf=0;  
  241.         taller=-1;  
  242.     }  
  243.     else if (p->bf==0)  
  244.     {  
  245.         p->bf=1;  
  246.         taller=0;  
  247.     }  
  248.     else        //p->bf=1  
  249.     {  
  250.         p1=p->lchild;  
  251.         if (p1->bf==0)          //需作LL调整  
  252.         {  
  253.             p->lchild=p1->rchild;  
  254.             p1->rchild=p;  
  255.             p1->bf=-1;  
  256.             p->bf=1;  
  257.             p=p1;  
  258.             taller=0;  
  259.         }  
  260.         else if (p1->bf==1)     //需作LL调整  
  261.         {  
  262.             p->lchild=p1->rchild;  
  263.             p1->rchild=p;  
  264.             p->bf=p1->bf=0;  
  265.             p=p1;  
  266.             taller=1;  
  267.         }  
  268.         else                    //需作LR调整  
  269.         {  
  270.             p2=p1->rchild;  
  271.             p1->rchild=p2->lchild;  
  272.             p2->lchild=p1;  
  273.             p->lchild=p2->rchild;  
  274.             p2->rchild=p;  
  275.             if (p2->bf==0)  
  276.             {  
  277.                 p->bf=0;  
  278.                 p1->bf=0;  
  279.             }  
  280.             else if (p2->bf==1)  
  281.             {  
  282.                 p->bf=-1;  
  283.                 p1->bf=0;  
  284.             }  
  285.             else  
  286.             {  
  287.                 p->bf=0;  
  288.                 p1->bf=1;  
  289.             }  
  290.             p2->bf=0;  
  291.             p=p2;  
  292.             taller=1;  
  293.         }  
  294.     }  
  295. }  
  296. void Delete2(BSTNode *q,BSTNode *&r,int &taller)  
  297. //由DeleteAVL()调用,用于处理被删结点左右子树均不空的情况  
  298. {  
  299.     if (r->rchild==NULL)  
  300.     {  
  301.         q->key=r->key;  
  302.         q=r;  
  303.         r=r->lchild;  
  304.         free(q);  
  305.         taller=1;  
  306.     }  
  307.     else  
  308.     {  
  309.         Delete2(q,r->rchild,taller);  
  310.         if (taller==1)  
  311.             RightProcess1(r,taller);  
  312.     }  
  313. }  
  314. int DeleteAVL(BSTNode *&p,KeyType x,int &taller) //在AVL树p中删除关键字为x的结点  
  315. {  
  316.     int k;  
  317.     BSTNode *q;  
  318.     if (p==NULL)  
  319.         return 0;  
  320.     else if (x<p->key)  
  321.     {  
  322.         k=DeleteAVL(p->lchild,x,taller);  
  323.         if (taller==1)  
  324.             LeftProcess1(p,taller);  
  325.         return k;  
  326.     }  
  327.     else if (x>p->key)  
  328.     {  
  329.         k=DeleteAVL(p->rchild,x,taller);  
  330.         if (taller==1)  
  331.             RightProcess1(p,taller);  
  332.         return k;  
  333.     }  
  334.     else            //找到了关键字为x的结点,由p指向它  
  335.     {  
  336.         q=p;  
  337.         if (p->rchild==NULL)        //被删结点右子树为空  
  338.         {  
  339.             p=p->lchild;  
  340.             free(q);  
  341.             taller=1;  
  342.         }  
  343.         else if (p->lchild==NULL)   //被删结点左子树为空  
  344.         {  
  345.             p=p->rchild;  
  346.             free(q);  
  347.             taller=1;  
  348.         }  
  349.         else                        //被删结点左右子树均不空  
  350.         {  
  351.             Delete2(q,q->lchild,taller);  
  352.             if (taller==1)  
  353.                 LeftProcess1(q,taller);  
  354.             p=q;  
  355.         }  
  356.         return 1;  
  357.     }  
  358. }  
  359. int main()  
  360. {  
  361.     BSTNode *b=NULL;  
  362.     int i,j,k;  
  363.     KeyType a[]= {16,3,7,11,9,26,18,14,15},n=9; //例10.5  
  364.     printf(" 创建一棵AVL树:\n");  
  365.     for(i=0; i<n; i++)  
  366.     {  
  367.         printf("   第%d步,插入%d元素:",i+1,a[i]);  
  368.         InsertAVL(b,a[i],j);  
  369.         DispBSTree(b);  
  370.         printf("\n");  
  371.     }  
  372.     printf("   AVL:");  
  373.     DispBSTree(b);  
  374.     printf("\n");  
  375.     printf(" 删除结点:\n");                     //例10.6  
  376.     k=11;  
  377.     printf("   删除结点%d:",k);  
  378.     DeleteAVL(b,k,j);  
  379.     printf("   AVL:");  
  380.     DispBSTree(b);  
  381.     printf("\n");  
  382.     k=9;  
  383.     printf("   删除结点%d:",k);  
  384.     DeleteAVL(b,k,j);  
  385.     printf("   AVL:");  
  386.     DispBSTree(b);  
  387.     printf("\n");  
  388.     k=15;  
  389.     printf("   删除结点%d:",k);  
  390.     DeleteAVL(b,k,j);  
  391.     printf("   AVL:");  
  392.     DispBSTree(b);  
  393.     printf("\n\n");  
  394.     return 0;  
  395. }  

运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值