平衡二叉树的插入(删除)操作

  1. #include <stdlib.h>   
  2. #include <stdio.h>   
  3. #include <string.h>   
  4. /* 二叉平衡树节点的定义 */  
  5. typedef struct _AVLNode{  
  6.     int data;  
  7.     int bf;/*平衡因子*/  
  8.     struct _AVLNode *lchild,*rchild;  
  9. }AVLNode,*AVLTree;  
  10. /*创建一个二叉搜索树节点,x为关键字值 */  
  11. AVLTree Create(int x)  
  12. {  
  13.     AVLTree avl=(AVLTree)malloc(sizeof(AVLNode));  
  14.     if(avl==NULL)  
  15.     {  
  16.         perror("创建失败");  
  17.         exit(1);  
  18.     }  
  19.     avl->data=x;  
  20.     avl->bf=0;  
  21.     avl->lchild=avl->rchild=NULL;  
  22.     return avl;  
  23. }  
  24. /*左旋转函数*/  
  25. void LRotation(AVLTree *avl,int *unbalance)  
  26. {  
  27.     AVLTree u,r=(*avl)->lchild;  
  28.     if(r->bf==1)//LL 旋转   
  29.     {  
  30.         (*avl)->lchild=r->rchild;  
  31.         r->rchild=*avl;  
  32.         (*avl)->bf=0;  
  33.         (*avl)=r;/*(*avl)指向新子树的根*/  
  34.     }  
  35.     else/*LR旋转*/  
  36.     {  
  37.         u=r->rchild;  
  38.         r->rchild=u->lchild;  
  39.         u->lchild=r;  
  40.         (*avl)->lchild=u->rchild;  
  41.         u->rchild=*avl;  
  42.         switch(u->bf)  
  43.         {  
  44.             case 1:   
  45.                 (*avl)->bf=-1;  
  46.                 r->bf=0;  
  47.                 break;  
  48.             case 0:  
  49.                 (*avl)->bf=r->bf=0;  
  50.                 break;  
  51.             case -1:  
  52.                 (*avl)->bf=0;  
  53.                 r->bf=1;  
  54.         }  
  55.         *avl=u;/*(*avl)指向新子树的根*/  
  56.     }  
  57.     (*avl)->bf=0;  
  58.     *unbalance=0;  
  59. }  
  60. void RRotation(AVLTree *avl,int *unbalance)  
  61. {  
  62.     AVLTree u,r=(*avl)->rchild;  
  63.     if(r->bf==-1)//RR 旋转   
  64.     {  
  65.         (*avl)->rchild=r->lchild;  
  66.         r->lchild=(*avl);  
  67.         (*avl)->bf=0;  
  68.         (*avl)=r;/*(*avl)指向新子树的根*/  
  69.     }  
  70.     else  
  71.     {  
  72.         u=r->lchild;  
  73.         r->lchild=u->rchild;  
  74.         u->rchild=r;  
  75.         (*avl)->rchild=u->lchild;  
  76.         u->lchild=(*avl);  
  77.         switch(u->bf)  
  78.         {  
  79.             case -1:   
  80.                 (*avl)->bf=-1;  
  81.                 r->bf=0;  
  82.                 break;  
  83.             case 0:  
  84.                 (*avl)->bf=r->bf=0;  
  85.                 break;  
  86.             case 1:  
  87.                 (*avl)->bf=0;  
  88.                 r->bf=1;  
  89.         }  
  90.             (*avl)=u;/*(*avl)指向新子树的根*/  
  91.     }  
  92.     (*avl)->bf=0;  
  93.     *unbalance=0;  
  94. }  
  95. void Insert(AVLTree* avl,int x,int *unbalance)  
  96. {  
  97.     if(*avl==NULL)  
  98.     {/*生成新结点再插入*/  
  99.         *avl=Create(x);  
  100.         *unbalance=1;  
  101.     }  
  102.     else if(x<((*avl)->data))/*新结点插入左子树*/  
  103.     {  
  104.         Insert(&((*avl)->lchild),x,unbalance);  
  105.         if(*unbalance)  
  106.         {  
  107.             switch((*avl)->bf)  
  108.             {  
  109.                 case -1:  
  110.                     (*avl)->bf=0;  
  111.                     *unbalance=0;  
  112.                     break;  
  113.                 case 0:  
  114.                     (*avl)->bf=1;  
  115.                     break;  
  116.                 case 1:  
  117.                     LRotation(avl,unbalance);  
  118.             }  
  119.         }  
  120.     }  
  121.         else if(x==(*avl)->data)/*元素存在直接返回*/  
  122.         {  
  123.             return ;  
  124.         }  
  125.         else/*新结点插入右子树*/  
  126.         {  
  127.             Insert(&((*avl)->rchild),x,unbalance);  
  128.             if(*unbalance)  
  129.             {  
  130.                 switch((*avl)->bf)  
  131.                 {  
  132.                 case 1:(*avl)->bf=0;  
  133.                     *unbalance=0;break;  
  134.                     break;  
  135.                 case 0:  
  136.                     (*avl)->bf=-1;  
  137.                     break;  
  138.                 case -1:  
  139.                     RRotation(avl,unbalance);  
  140.                 }  
  141.             }  
  142.         }  
  143. }  
  144. /*中序遍历 */  
  145. void  InOrder(AVLTree bst)  
  146. {  
  147.     if(bst==NULL)  
  148.         return ;  
  149.     else  
  150.     {  
  151.         InOrder(bst->lchild);  
  152.         printf("%d ",bst->data);  
  153.         InOrder(bst->rchild);  
  154.           
  155.     }  
  156. }  
  157. /*前序遍历 */  
  158. void  PreOrder(AVLTree bst)  
  159. {  
  160.     if(bst==NULL)  
  161.         return ;  
  162.     else  
  163.     {  
  164.         printf("%d ",bst->data);  
  165.         PreOrder(bst->lchild);  
  166.         PreOrder(bst->rchild);  
  167.           
  168.     }  
  169. }  
  170. int main()  
  171. {  
  172.     AVLTree avl=NULL;  
  173.     int balance;  
  174.     Insert(&avl,45,&balance);  
  175.     Insert(&avl,28,&balance);  
  176.     Insert(&avl,15,&balance);  
  177.     Insert(&avl,12,&balance);  
  178.     Insert(&avl,14,&balance);     
  179.     Insert(&avl,13,&balance);  
  180.     Insert(&avl,11,&balance);  
  181.     Insert(&avl,47,&balance);  
  182.     Insert(&avl,57,&balance);  
  183.     Insert(&avl,46,&balance);  
  184.     InOrder(avl);  
  185.     printf("\n");  
  186.     PreOrder(avl);  
  187. }  

二叉平衡树的删除与插入类似,先采用二叉搜索树的删除方法,删除结点,再在必要时通过重新平衡,恢复平衡性和排序性。当删除X有两个孩子时,使用替代法,将问题转化为删除只有一个孩子的结点的问题,然后删除之。由q指向实际被删除的结点,它最多只有一个非空子树,当结点q由它的孩子取代后,该树变矮,这种情况会影响其祖先的平衡性,应重新平衡。使用short变量来记录对其双亲(p)平衡性的影响。

同插入的情况一样,我们通过以下三种情况来分析二叉平衡树的删除。

情况一:结点p的平衡因子为0

从p的子树上删除结点后,该子树变矮,但以p为根的子树的高度不变,只是平衡因子变化了。只要修改平衡因子即可。令short变量为0,表示算法终止。如图所示:


情况二:从结点p的较高子树上删除一个结点

从p的较高子树上删除节点后,树的高度降低,但是一p为根的子树依然是平衡的。因此将p的平衡因子置位1。因为p的平衡因子改变了可能影响其双亲的平衡因子,故需要是short为1,表示继续检查p的双亲为根的子树的平衡性是否因为p的变矮而破坏。如图所示:


情况三:从结点p的矮的子树上删除一个结点

从p的较矮子树上删除一个结点,以p为根的子树的平衡性被破坏,要通过旋转来恢复这棵子树的平衡性。设r是p的较高子树,根据r的平衡因子,可以进一步细分一下三种。

(1)结点r的平衡因子为0

则应采用单一旋转,并修改p和r的平衡因子的值。重新平衡后,新子树与原子树有相同的高度,不会影响二叉平衡树的其余部分,令short=0,算法终止。如图所示:


(2)结点r的平衡因子和p的平衡因子同号

仍采用单一旋转,旋转后p和r的平衡因子均为0.重新平衡后,新子树变矮,故short=1,需要继续考察p的双亲的平衡性。


(3)结点r的平衡性和p的平衡性异号

则采用双重旋转。令u是r的较高子树的根,它将成为新子树的根,取代p为根的子树,u的平衡因子为0,p和r的平衡因子做相应的修改,这棵以u为根的子树是平衡的,但高度变矮了。故short=1;继续向根方向考察。如图所示:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值