平衡二叉树
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 }