平衡二叉树

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #define LH 1   //左子树高
  4 #define EH 0   //左右子树一样高
  5 #define RH -1    //右子树高 
  6 #define max 20    //最多可输入的结点数 
  7 typedef struct node{
  8     int data;
  9     int bf;   //平衡因子,合法可能取值有1、0、-1 
 10     struct node *lc,*rc;
 11 }bit,*bitptr; 
 12 
 13 void r_move(bitptr &t)    //右旋(LL),以t为根节点进行右旋操作,新生成的根节点也用t返回 
 14 {
 15     bitptr p;
 16     p = t->lc ;
 17     t->lc = p->rc ;
 18     p->rc = t;
 19     t = p;
 20 }
 21 
 22 void l_move(bitptr &t)    //左旋(RR),以t为根节点进行左旋操作,新生成的根节点也用t返回 
 23 {
 24     bitptr p;
 25     p = t->rc ;
 26     t->rc = p->lc ;
 27     p->lc = t;
 28     t = p;
 29 }
 30 
 31 void l_balance(bitptr &t)   //左平衡移动,共包含两种情况(LL、LR),需要判断执行 ,t返回新生成的根节点 
 32 {
 33     bitptr p,q;
 34     p = t->lc ;
 35     switch(p->bf ){     //检查t的左子树的平衡因子,判断是两种情况中的哪种 
 36         case LH:            //新插入结点在t的左子树的左子树中,为LL型,做单步右旋处理 
 37             t->bf = p->bf = EH;    //调整旋转后的相应三个结点的平衡因子,新插入结点平衡因子不变仍为EH,故不用写出 
 38             r_move(t);     
 39             break;
 40         case RH:           //新插入结点在t的左子树的右子树上,判断属于三种情况中的哪一种,做双次旋转处理 
 41             q = p->rc ;          //t中的左孩子的右子树根,可以是新插入结点也可以是新插入结点的父节点 
 42             switch(q->bf ){      //针对每种情况修改相关三个结点的平衡因子 
 43                 case LH:              //新插入结点为q的左孩子 
 44                     t->bf = RH;   p->bf = EH;
 45                     break;
 46                 case EH:             //新插入结点就是q 
 47                     t->bf = p->bf = EH;
 48                     break;
 49                 case RH:            //新插入结点为q的右孩子 
 50                     t->bf = EH;   p->bf = LH;
 51                     break;
 52             }
 53             q->bf = EH;
 54             l_move(t->lc );        //将t的左孩子做左旋处理,同时完成旋转后的排序调整 
 55             r_move(t);             //对t及其左孩子和子孙做右旋处理 
 56     } 
 57 }
 58 
 59 void r_balance(bitptr &t)    //右平衡移动,包含两种情况(RR、RL),通过switch语句根据结点的bf分别进行判断 
 60 {
 61     bitptr p,q;
 62     p = t->rc ;
 63     switch(p->bf ){    //检查根节点右孩子的平衡情况,判断属于RR、RL中的哪一种情况 
 64         case RH:           //RR 
 65             t->bf = p->bf = EH;
 66             l_move(t);
 67             break;
 68         case LH:        //RL 
 69             q = p->lc ;     //t的右孩子的左孩子 ,可以是新插入的结点也可以是新插入结点的父节点 
 70             switch(q->bf ){      //检查该结点的平衡因子,判断属于那种情况修改相应的平衡因子再进行旋转修改 
 71                 case LH:            //新插入结点为该结点的左孩子 
 72                     t->bf = EH;   p->bf = RH;
 73                     break;
 74                 case EH:           //新插入结点为该结点 
 75                     t->bf = p->bf = EH;
 76                     break;
 77                 case RH:          //新插入结点为该结点的右孩子 
 78                     t->bf = LH;   p->bf = EH;
 79                     break;
 80             }
 81             q->bf = EH;
 82             r_move(t->rc );   //调整t的右孩子及其右孩子的左孩子的平衡状态,并完成排序 
 83             l_move(t); 
 84     }
 85 }
 86 
 87 int createAVL(bitptr &t,int key,int &istall)    //依次传入一个数据进行插入,并从接入的结点开始尽心递归判断是否需要进行平衡调整 
 88 //t指向生成树的树根,调整后的平衡树的树根也由t指向,istall代表是否成功插入一个结点 
 89 {
 90     if(!t){       //代表生成了新的结点,此结点时叶子节点 
 91         t = (bitptr)malloc(sizeof(bit*));
 92         t->data = key;
 93         t->lc = t->rc = NULL;
 94         t->bf = EH;
 95         istall = 1;
 96     }
 97     else{       //代表正在找寻适合的位置将数据插入 
 98         if(t->data == key){    //若树中已存在该数据则不将key进行插入 
 99             istall = 0;
100             return 0;
101         }
102         if(t->data > key){    //在跟根节点的右子树中继续寻找合适位置 
103             if(!createAVL(t->lc ,key,istall))   return 0;   //在树中找到了相等数据,不做处理 
104             if(istall){      //结点成功插入,即树长高,根据插入结点的父节点判断属于哪一种插入情况,调整相关数据 
105                 switch(t->bf ){
106                     case LH:    //该父节点原来左子树较高,进行调整 
107                         l_balance(t); istall = 0;
108                         break;
109                     case EH:      //该父节点原来左右子树一样高,增加左孩子以后不需要调整 
110                         t->bf = LH;  istall = 1;
111                         break;
112                     case RH:        //该父节点原来右子树较高,增加左孩子以后左右子树相等,不需要调整 
113                         t->bf = EH;  istall = 0;
114                         break;
115                 }
116             }
117         }
118         else{
119             if(!createAVL(t->rc ,key,istall))   return 0;
120             if(istall){    //结点成功插入右子树中,判断是否需要进行平衡调整 
121                 switch(t->bf ){
122                     case LH:      //该父节点原来左子树较高,增加右孩子,左右子树高度相等,不需要调整 
123                         t->bf = EH;  istall = 0;
124                         break;
125                     case EH:       //该父节点原来左右子树相等,增加右孩子不影响平衡,不需要调整 
126                         t->bf = RH;  istall = 1;
127                         break;
128                     case RH:      //该父节点原来右子树较高,增加右孩子破坏平衡,需要进行平衡调整 
129                         r_balance(t);  istall = 0;
130                         break;
131                 }
132             }
133         }
134     }
135     return 1;
136 }
137 
138 void print(bitptr t,int level)   //凹入表形式逆中序输出树 ,level初值为1 
139 {
140     if(t){
141         print(t->rc ,level + 1);
142         for(int i = 1;i < level;i++)     printf(" ");
143         printf("%d\n",t->data );
144         print(t->lc ,level + 1);
145     }
146 }
147 
148 int main()
149 {
150     int num[max],i = 0,a,j,is = 1,l = 1;
151     bitptr root;
152     
153     scanf("%d",&a);
154     while(a != -1){   //输入待插入序列,以‘-1’作为结束符 
155         num[i] = a;
156         i++;
157         scanf("%d",&a);
158     }
159     root = NULL;   //建立根节点 
160     for(j = 0;j < i;j++){
161         createAVL(root,num[j],is);
162         printf("插入结点%d后平衡二叉树为:\n",num[j]);
163         print(root,l);
164     }
165     return 0;
166  } 

 

posted @ 2020-04-22 20:15  简单记录一下咯  阅读(145)  评论(0编辑  收藏  举报