第十四周项目一 平衡二叉树

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值