平衡二叉树

感情迁移 提交于 2020-02-28 06:47:55
  1 #include<time.h>
  2 #include<stdio.h>  
  3 #include<stdlib.h> 
  4 //左子树比右子树高一
  5 #define LH 1
  6 //左子树和右子树一样高
  7 #define EH 0
  8 //左子树比右子树低一
  9 #define RH -1
 10 #define EQ(a,b) ((a) == (b))
 11 #define LT(a,b) ((a) < (b))
 12 #define LQ(a,b)((a) <= (b))
 13 
 14 typedef struct BSTNode
 15 {
 16     int data;
 17     int bf;
 18     BSTNode * lchild;
 19     BSTNode * rchild;
 20 }BSTNode;
 21 typedef BSTNode * BSTree;
 22 
 23 //    左旋
 24 void leftRotate(BSTree & root) 
 25 {
 26     BSTree rc = root->rchild;
 27     root->rchild = rc->lchild;
 28     rc->lchild = root;
 29     root = rc;
 30 }
 31 //    右旋
 32 void rightRotate(BSTree & root) 
 33 {
 34     BSTree lc = root->lchild;
 35     root->lchild = lc->rchild;
 36     lc->rchild = root;
 37     root = lc;
 38 }
 39 //    对二叉树root进行左平衡处理(LL型和LR型)
 40 void leftBalance(BSTree & root) 
 41 {
 42     BSTree lc = root->lchild;
 43     switch (lc->bf) 
 44     {
 45         //LL型的只需要进行右旋操作
 46     case LH:
 47         //右旋之后根和左子树都的平衡的
 48         root->bf = EH;
 49         lc->bf = EH;
 50         //右旋操作
 51         rightRotate(root);
 52         break;
 53         //LR型的需要进行左旋操作,然后右旋操作
 54     case RH:
 55         BSTree rc = lc->rchild;
 56         switch (rc->bf) 
 57         {
 58         case LH:
 59             root->bf = RH;
 60             lc->bf = EH;
 61             break;
 62         case EH:
 63             root->bf = EH;
 64             lc->bf = EH;
 65             break;
 66         case RH:
 67             root->bf = EH;
 68             lc->bf = LH;
 69             break;
 70         }
 71         rc->bf = EH;
 72         leftRotate(root->lchild);
 73         rightRotate(root);
 74         break;
 75     }
 76 }
 77 //    功能:对二叉树root进行左平衡处理(RR型和RL型)
 78 void rightBalance(BSTree & root) 
 79 {
 80     BSTree rc = root->rchild;
 81     switch (rc->bf) 
 82     {
 83         //RR型只需要做左旋操作
 84     case RH:
 85         root->bf = EH;
 86         rc->bf = EH;
 87         //左旋操作
 88         leftRotate(root);
 89         break;
 90         //RL型需要先做右旋操作,然后做左旋操作
 91     case LH:
 92         BSTree lc = rc->lchild;
 93         switch (lc->bf) 
 94         {
 95         case LH:
 96             root->bf = EH;
 97             rc->bf = RH;
 98             break;
 99         case EH:
100             root->bf = EH;
101             rc->bf = EH;
102             break;
103         case RH:
104             root->bf = LH;
105             rc->bf = EH;
106             break;
107         }
108         lc->bf = EH;
109         rightRotate(root->rchild);
110         leftRotate(root);
111         break;
112     }
113 }
114 //    功能:把元素data插入平衡二叉树root中
115 bool insert(BSTree & root, int data, bool & taller) 
116 {
117     if (NULL == root) 
118     {
119         root = (BSTree)malloc(sizeof(BSTNode));
120         root->rchild = NULL;
121         root->lchild = NULL;
122         root->data = data;
123         root->bf = EH;
124         taller = true;
125     }
126     else
127     {
128         //该元素已经在平衡二叉树中存在了
129         if (data == root->data) 
130         {
131             taller = false;
132             return false;
133         }
134         //插入左子树
135         else if (data < root->data) 
136         {
137             if (!insert(root->lchild, data, taller)) 
138             {
139                 return false;
140             }
141             //插入成功,并且树变高了
142             if (taller) 
143             {
144                 switch (root->bf) 
145                 {
146                 case LH:
147                     leftBalance(root);
148                     //平衡二叉树做完左平衡操作后
149                     //树高没有变化,故taller = false
150                     taller = false;
151                     break;
152                 case EH:
153                     root->bf = LH;
154                     //原来是平衡的故插入一个元素后
155                     //树高必然变高
156                     taller = true;
157                     break;
158                 case RH:
159                     root->bf = EH;
160                     //原来是右子树比左子树高,但是当向左子树中
161                     //插入一个元素的时候,树变平衡了,故taller = false
162                     taller = false;
163                     break;
164                 default:
165                     break;
166                 }
167             }
168         }
169         //插入右子树
170         else 
171         {
172             if (!insert(root->rchild, data, taller)) 
173             {
174                 return 0;
175             }
176             if (taller) 
177             {
178                 switch (root->bf) 
179                 {
180                 case LH:
181                     root->bf = EH;
182                     taller = false;
183                     break;
184                 case EH:
185                     root->bf = RH;
186                     taller = true;
187                     break;
188                 case RH:
189                     rightBalance(root);
190                     taller = false;
191                     break;
192                 }
193             }
194         }
195     }
196     return true;
197 }
198 //   在平衡二叉树中查找int节点
199 int * search(BSTree & root, int data) 
200 {
201     if (root ==NULL) 
202     {
203         return NULL;
204     }
205     
206     if (root->data == data) 
207     {
208         return &root->data;
209     }
210     else if (data < root->data) 
211     {
212         return search(root->lchild, data);
213     } 
214     else 
215     {
216         return search(root->rchild, data);
217     }
218 }
219 //    功能:输出平衡二叉树中的所有的元素(小->大,中序遍历)
220 void print(BSTree & root)
221 {
222     if (NULL == root) 
223     {
224         return ;
225     }
226     
227     print(root->lchild);
228     printf("%d ",root->data);
229     print(root->rchild);
230 }
231 //    功能:释放平衡二叉树的空间
232 void clear(BSTree & root) 
233 {
234     if (NULL == root) 
235     {
236         return ;
237     }
238     clear(root->lchild);
239     clear(root->rchild);
240     free(root);
241 }
242 int DeleteAVL(BSTree &T, int key, bool &shorter){
243     if (!T)
244     {//No such key
245         shorter = false;
246         return 0;
247     }
248     else
249     {
250         if (EQ(key, T->data))    //找到了需要删除的结点
251         {
252             //如果该结点的lchild 和
253             //rchild 至少有一个为NULL
254             //则大功告成,否则请参照
255             //下方解释
256             BSTree q = T;
257             if (!T->lchild)//如果该结点的lchild 为NULL
258             {
259                 q = T;
260                 T = T->rchild;
261                 free(q);
262                 shorter = true;
263                 return 1;
264             }
265             else if (!T->rchild){//如果该结点的rchild 为 NULL
266                 q = T;
267                 T = T->lchild;//如果不是&(引用)的强大功能,这句话是没有意义的
268                 free(q);
269                 shorter = true;
270                 return 1;
271             }
272             else {
273                 //删除一个左右孩子都不为空的结点
274                 //使该结点的直接前驱p的data替换该结点的data
275                 //然后改变key=p.data
276                 BSTree s = T->lchild;
277                 while (s->rchild)
278                     s = s->rchild;
279                 T->data = s->data;
280                 key = s->data;//Now, delete the vertice whose data was the new key
281             }
282         }
283         if (LQ(key, T->data)){//这里与InsertAVL不同
284             if (!DeleteAVL(T->lchild, key, shorter)) return 0;
285             if (shorter){
286                 switch(T->bf){
287                 case LH:T->bf = EH; shorter = true;break;
288                 case EH:T->bf = RH;shorter = false;break;
289                 case RH:rightBalance(T); 
290                     if (T->rchild->bf == EH)
291                         shorter = false;
292                     else 
293                         shorter = true;break;
294                 }
295             }
296         }
297         else{
298             if (!DeleteAVL(T->rchild, key, shorter)) return 0;
299             if (shorter){
300                 switch(T->bf){
301                 case LH:leftBalance(T);
302                     if (T->lchild->bf == EH)
303                         shorter = false;
304                     else 
305                         shorter = true;break;
306                 case EH:T->bf = LH; shorter = false;break;
307                 case RH:T->bf = EH;shorter = true;break;
308                 }
309             }
310         }
311     }
312     return 1;
313 }//Delete
314 void menu()  
315 {  
316     printf("⊙☆⊙ ⊙☆⊙ ⊙☆⊙ ⊙☆⊙    主菜单     ⊙☆⊙ ⊙☆⊙ ⊙☆⊙ ⊙☆⊙\n");  
317     printf("⊙☆⊙ ⊙☆⊙ ⊙☆⊙请按№ 1:连续插入数据 输入0结束插入⊙☆⊙ ⊙☆⊙ ⊙☆⊙\n");  
318     printf("⊙☆⊙ ⊙☆⊙ ⊙☆⊙请按№ 2:查找数据                  ⊙☆⊙ ⊙☆⊙ ⊙☆⊙\n");  
319     printf("⊙☆⊙ ⊙☆⊙ ⊙☆⊙请按№ 3删除特定数据               ⊙☆⊙ ⊙☆⊙ ⊙☆⊙\n");  
320     printf("⊙☆⊙ ⊙☆⊙ ⊙☆⊙请按№ 4输出当前结果                   ⊙☆⊙ ⊙☆⊙ ⊙☆⊙\n"); 
321     printf("⊙☆⊙ ⊙☆⊙ ⊙☆⊙请按№ 5结束程序                   ⊙☆⊙ ⊙☆⊙ ⊙☆⊙\n");
322 }  
323 int main()
324 {
325     BSTree root = NULL;
326     int num,n;
327     bool taller = false,shorter;
328     system("color 2e");  
329     menu();
330     while(1)  
331     {  
332         scanf("%d",&num); 
333         //if(num==5) break;
334         switch (num)  
335         {  
336         case 1:
337             system("cls");
338             printf("请插入数据 ,输入0结束插入\n");
339             while(scanf("%d",&n))
340             {
341                 if(n==0) break;
342                 else insert(root,n,taller);
343             }
344             system("cls");
345             menu();
346             break;
347         case 2: 
348             system("cls");
349             printf("请输入要查询的数\n");
350             scanf("%d",&n);
351             int *p;
352             p=search(root,n);
353             if (p==NULL) 
354             {
355                 printf("对不起 没有找到 %d!\n",n);
356             }
357             else 
358             {
359                 printf("恭喜你 数据中存在 %d!\n",n);
360             }
361             menu();
362             break;  
363         case 3: 
364             system("cls");
365             printf("请输入要删除的数据\n");
366             scanf("%d",&n);
367             DeleteAVL(root,n,shorter);
368             menu();
369             break;
370         case 4:
371             system("cls");
372             print(root); 
373             printf("输入0进入主菜单\n");
374             scanf("%d",&n);
375             if(!n)
376               menu();
377             break;
378         case 5:
379             clear(root);
380             return 0;        
381         }
382     }
383     return 0;
384 }

原文转自:http://blog.csdn.net/hnust_xiehonghao/article/details/7938869

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!