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 }