算法11---红黑树的实现
1 #include <iostream> 2 using namespace std; 3 #define BLACK 0 4 #define RED 1 5 #define Nil -1 6 #define LEN sizeof(struct Tree) 7 struct Tree 8 { 9 struct Tree*left; 10 struct Tree*right; 11 struct Tree*parent; 12 int key; 13 int color; 14 }; 15 16 struct Tree *root=NULL; 17 struct Tree *nil=NULL; 18 void LEFT_ROTATE(struct Tree*x) 19 {//左旋转:分三个步骤①②③来叙述旋转代码的。 20 struct Tree*y=x->right;//设置y结点。 21 x->right=y->left;//本行代码以及下面的if结构表达的是“y的左孩子成为x的右孩子”。① 22 if(y->left!=nil) 23 { 24 y->left->parent=x; 25 } 26 y->parent=x->parent;//本行代码以及下面的if-else结构表达的过程是“y成为该子树新的根”。② 27 if(x->parent==nil) 28 { 29 root=y; 30 } 31 else if(x==x->parent->left) 32 { 33 x->parent->left=y; 34 } 35 else x->parent->right=y; 36 y->left=x;//本行代码以及下面一行都表达了“x成为y的左孩子”。③ 37 x->parent=y; 38 } 39 void RIGHT_ROTATE(struct Tree*x) 40 {//右旋转:分三个步骤①②③来叙述旋转代码的。 41 struct Tree*y=x->left;//设置y结点。 42 x->left=y->right;//本行代码以及下面的if结构表达的是“y的左孩子成为x的右孩子”。① 43 if(y->right!=nil) 44 { 45 y->right->parent=x; 46 } 47 y->parent=x->parent;//本行代码以及下面的if-else结构表达的过程是“y成为该子树新的根”。② 48 if(x->parent==nil) 49 { 50 root=y; 51 } 52 else if(x==x->parent->right) 53 { 54 x->parent->right=y; 55 } 56 else x->parent->left=y; 57 y->right=x;//本行代码以及下面一行都表达了“x成为y的左孩子”。③ 58 x->parent=y; 59 } 60 void RB_INSERT_INSERT_FIXUP(struct Tree*z) 61 { 62 while (z->parent->color==RED) 63 { 64 if (z->parent==z->parent->parent->left) 65 { 66 struct Tree*y=z->parent->parent->right;//叔结点 67 if (y->color==RED)//情况一:叔结点为红色 68 {//给p1,y,p2着色以保持性质5。并且解决了z的父结点和z都是红色结点问题 69 z->parent->color=BLACK; 70 y->color=BLACK; 71 z->parent->parent->color=RED; 72 z=z->parent->parent;//把z的祖父结点当成新结点z进入下一次循环 73 } 74 else 75 { 76 if (z==z->parent->right)//情况二:检查z是否是一个右孩子且叔结点为黑色,前提是p1结点不是叶子结点 77 {//使用一个左旋让情况2转变为情况3 78 z=z->parent; 79 LEFT_ROTATE(z);//由于进入if语句后可知旋转结点不可能是叶子结点,这样就不用判断z是否是叶子结点了。 80 } 81 z->parent->color=BLACK;//情况三:是z是一个左孩子且叔结点为黑色,改变z的父和祖父结点颜色并做一次右旋,以保持性质5 82 z->parent->parent->color=RED; 83 RIGHT_ROTATE(z->parent->parent);//由于p2可能是叶子结点,所以最好还是用一个if判断 84 } 85 } 86 else//下面else分支类似于上面,注意到else分支的情况2和情况3所做旋转正好是if分支情况的逆。 87 { 88 struct Tree*y=z->parent->parent->left; 89 if (y->color==RED) 90 { 91 z->parent->color=BLACK; 92 y->color=BLACK; 93 z->parent->parent->color=RED; 94 z=z->parent->parent; 95 } 96 else 97 { 98 if (z==z->parent->left) 99 { 100 z=z->parent; 101 RIGHT_ROTATE(z); 102 } 103 z->parent->color=BLACK; 104 z->parent->parent->color=RED; 105 LEFT_ROTATE(z->parent->parent); 106 } 107 } 108 } 109 root->color=BLACK;//最后给根结点着为黑色。 110 } 111 void RB_INSERT(struct Tree*z) 112 { 113 struct Tree*y=nil; 114 struct Tree*x=root; 115 while (x!=nil) 116 { 117 y=x; 118 if (z->key<x->key) 119 { 120 x=x->left; 121 } 122 else x=x->right; 123 } 124 z->parent=y; 125 if (y==nil) 126 { 127 root=z; 128 } 129 else if(z->key<y->key) 130 { 131 y->left=z; 132 } 133 else y->right=z; 134 z->left=nil;//给插入结点左右孩子赋值为空。 135 z->right=nil; 136 z->color=RED;//给插入结点着为红色。 137 RB_INSERT_INSERT_FIXUP(z); 138 } 139 void RB_TRANSPLANT(struct Tree*u,struct Tree*v) 140 { 141 if (u->parent==nil) 142 root=v; 143 else if(u==u->parent->left) 144 u->parent->left=v; 145 else u->parent->right=v; 146 v->parent=u->parent; 147 } 148 //非递归版本的查找二叉查找树的最小值 149 struct Tree*ITERATIVE_TREE_MINIMUM(struct Tree*x) 150 { 151 while (x->left!=nil) 152 { 153 x=x->left; 154 } 155 return x; 156 } 157 //非递归版本的二叉查找树查找函数 158 struct Tree*ITERATIVE_TREE_SEARCH(struct Tree*x,int k) 159 { 160 while (x!=nil&&k!=x->key) 161 { 162 if (k<x->key) 163 { 164 x=x->left; 165 } 166 else x=x->right; 167 } 168 return x; 169 } 170 void RB_DELETE_FIXUP(struct Tree*x) 171 { 172 struct Tree*w=NULL;//w是x的兄弟结点 173 while (x!=root&&x->color==BLACK)//如果x是黑色并且不是根结点,才进行循环。 174 {//x是一个具有双重颜色的结点,调整的目的是把x的黑色属性向上移动。 175 if (x==x->parent->left) 176 { 177 w=x->parent->right; 178 if (w->color==RED)//情况一:x的兄弟结点w是红色的。 179 {//改变w和x.p的颜色+一次旋转使其变为情况二,三,四。 180 w->color=BLACK; 181 x->parent->color=RED; 182 LEFT_ROTATE(x->parent); 183 w=x->parent->right; 184 } 185 if (w->left->color==BLACK&&w->right->color==BLACK)//情况二:x的兄弟结点w是黑色的,而且w的两个子节点都是黑色。 186 { 187 w->color=RED;//从x和w上去掉一重黑色。x还是黑色,而w变为红色。 188 x=x->parent;//x结点向上移动成为新的待调整结点。 189 } 190 else 191 { 192 if (w->right->color==BLACK)//情况三:x的兄弟结点w是黑色的,w的左孩子是红色的,w的右孩子是黑色的。 193 {//交换w和w.left的颜色+旋转使其转变为情况四。 194 w->left->color=BLACK; 195 w->color=RED; 196 RIGHT_ROTATE(w); 197 w=x->parent->right; 198 } 199 w->color=x->parent->color;//以下是情况四:x的兄弟结点w是黑色的,且w的右孩子是红色的。 200 x->parent->color=BLACK;//置x.p和w.right为黑色+旋转使其去掉x的额外黑色。 201 w->right->color=BLACK; 202 LEFT_ROTATE(x->parent); 203 x=root;//x成为根结点,结束循环。 204 } 205 } 206 else//以下和上面的if分支类似,不做累述。 207 { 208 w=x->parent->left; 209 if (w->color==RED) 210 { 211 w->color=BLACK; 212 x->parent->color=RED; 213 RIGHT_ROTATE(x->parent); 214 w=x->parent->left; 215 } 216 if (w->left->color==BLACK&&w->right->color==BLACK) 217 { 218 w->color=RED; 219 x=x->parent; 220 } 221 else 222 { 223 if (w->left->color==BLACK) 224 { 225 w->right->color=BLACK; 226 w->color=RED; 227 LEFT_ROTATE(w); 228 w=x->parent->left; 229 } 230 w->color=x->parent->color; 231 x->parent->color=BLACK; 232 w->left->color=BLACK; 233 RIGHT_ROTATE(x->parent); 234 x=root; 235 } 236 } 237 }x->color=BLACK; 238 } 239 void RB_DELETE(struct Tree*z) 240 { 241 struct Tree*y=z,*x;//y为待删除或待移动结点 242 int y_original_color=y->color;//保存y的原始颜色,为做最后的调整做准备。 243 if (z->left==nil) 244 { 245 x=z->right;//x指向y的唯一子结点或者是叶子结点,保存x的踪迹使其移动到y的原始位置上 246 RB_TRANSPLANT(z,z->right);//把以z.right为根的子树替换以z为根的子树。 247 } 248 else if (z->right==nil) 249 { 250 x=z->left;//x指向y的唯一子结点或者是叶子结点,保存x的踪迹使其移动到y的原始位置上 251 RB_TRANSPLANT(z,z->left);//把以z.left为根的子树替换以z为根的子树。 252 } 253 else 254 { 255 y=ITERATIVE_TREE_MINIMUM(z->right);//找到z.right的后继。 256 y_original_color=y->color;//y的新的原始结点被重置。 257 x=y->right;//x指向y的唯一子结点或者是叶子结点,保存x的踪迹使其移动到y的原始位置上 258 if (y->parent==z) 259 { 260 x->parent=y;//由于z的父结点是要删除的结点,所以不能指向它,于是指向y 261 } 262 else 263 { 264 RB_TRANSPLANT(y,y->right);//把以y.right为根的子树替换以y为根的子树。 265 y->right=z->right; 266 y->right->parent=y; 267 } 268 RB_TRANSPLANT(z,y);//把以y为根的子树替换以z为根的子树。 269 y->left=z->left; 270 y->left->parent=y; 271 y->color=z->color;//把已经删除的结点颜色赋值给y,保证了y以上的树结构红黑性质不变。 272 } 273 if(y_original_color==BLACK) //y的原始颜色为黑色,说明需要调整红黑颜色。 274 RB_DELETE_FIXUP(x); 275 } 276 //中序遍历 277 void InOderTraverse(struct Tree *p) 278 { 279 if (p!=nil) 280 { 281 InOderTraverse(p->left); 282 cout<<p->key<<" "<<p->color<<" "<<endl; 283 InOderTraverse(p->right); 284 } 285 } 286 void main() 287 { 288 int array1[6] = {41, 38, 31, 12, 19, 8}; 289 nil=new struct Tree[LEN]; 290 nil->key=Nil;nil->color=BLACK; 291 root=nil; 292 int i=0; 293 struct Tree*ROOT=new struct Tree[LEN]; 294 ROOT->key=array1[i++]; 295 RB_INSERT(ROOT); 296 root=ROOT; 297 while (i!=6) 298 { 299 struct Tree*z=new struct Tree[LEN]; 300 z->key=array1[i]; 301 RB_INSERT(z); 302 i++; 303 } 304 InOderTraverse(root); 305 cout<<endl; 306 int array2[6] = {8, 12, 19, 31, 38, 41}; 307 for(i = 0; i< 6; i++) 308 { 309 struct Tree*x=ITERATIVE_TREE_SEARCH(root,array2[i]); 310 RB_DELETE(x); 311 InOderTraverse(root); 312 cout<<endl; 313 } 314 }