红黑树学习笔记(3)-删除操作
1、设删除的节点为$z$,另外定义节点$x,y$如下:
$y=\left\{\begin{matrix}z & z的左孩子或右孩子为空节点\\ Successor(z) & otherwise\end{matrix}\right.$
$x=\left\{\begin{matrix}y.left & y的左孩子不为空\\ y.right & otherwise\end{matrix}\right.$
其中$Successor$函数的定义在这里
接下来,用$x$替换节点$y$,所谓的替换就是$x$的父节点指向$y$的父节点,如果$y$是其父节点的左孩子,那么就让$y$的父节点的左孩子指向$x$,否则让$y$的父节点的右孩子指向$x$。然后令$z节点的值=y节点的值$.这样操作之后,实际上就是删掉了$z$节点。那么现在看节点$y$,其实是删掉了$z$节点的值和$y$节点的颜色,所以如果$y$节点的颜色是红色,那么本次删除操作就结束了,因为树的所有性质没有被破坏。相反如果$y$ 是黑色的,那么经过节点$x$的路径将会比不经过$x$的路径的黑色节点数少1。这种情况会修复节点$x$。下面是这个修复的过程。
2 首先假设$x$是其父节点的左孩子($x$是其父节点的右孩子的情况跟这个完全类似)。整个修复过程有四种情况。在修复的过程中,这四种情况之间的转换关系如下图所示:
也就是,如果是情况1,将会把情况1转换为情况2或者情况3、4,如果是情况3则会将其转换成情况4。
设$w$是$x$的兄弟节点。另外,在所有的情况中,满足这样的条件,就是经过节点$x$的路径将会比不经过$x$的路径的黑色节点数少1。
情况1: $w$的颜色为红色。这时候$x$父节点的颜色一定为黑色。如下图所示。首先将置$x$的父节点色颜色为红色,置$w$的颜色为黑色,然后左旋$x$的父节点,并重新令$w=x的兄弟节点$。这样,情况1将会转换为情况2或者情况3,4,也就是说情况2、3、4的$w$节点都是黑色。
情况2:$w$是黑色,$w$的两个孩子都是黑色。注意这时候$x$的父节点的颜色可能是红色也可能是黑色,下图是红色的情况,但是这两种情况执行的操作都是一样的。这时将$w$的颜色置为红色,然后令$x=x的父节点$。
情况3:$w$是黑色,$w$的右孩子是黑色(此时$w$的左孩子一定是红色,否则就是情况2了)。注意这时候$x$的父节点的颜色可能是红色也可能是黑色,下图是红色的情况,但是这两种情况执行的操作都是一样的。如下图所示。这种情况操作之后,将把$w$的右孩子转成红色节点,这也是情况4.现在交换$w$与其左孩子的颜色,然后右旋$w$,最后令$w=x现在的兄弟$
情况4:$w$是黑色,$w$的右孩子是红色。注意这时候$x$的父节点的颜色可能是红色也可能是黑色,下图是红色的情况,但是这两种情况执行的操作都是一样的。首先交换$w$与其父节点的颜色,然后置$w$的右孩子为黑色,最后左旋$x$的父节点。这一步之后可结束整个修复过程。
1 class RedBlackTree 2 { 3 private: 4 static const int BLACK=1; 5 static const int RED=0; 6 7 struct TreeNode 8 { 9 int key; 10 int color; 11 TreeNode* p; 12 TreeNode* left; 13 TreeNode* right; 14 }; 15 16 TreeNode* nullNode; 17 TreeNode* root; 18 19 TreeNode* NewNode(int val=0) 20 { 21 22 TreeNode* p=new TreeNode; 23 p->p=p->left=p->right=nullNode; 24 p->key=val; 25 26 return p; 27 } 28 29 30 31 void leftRotate(TreeNode* x) 32 { 33 TreeNode* y=x->right; 34 x->right=y->left; 35 if(y->left!=nullNode) y->left->p=x; 36 y->p=x->p; 37 if(x->p==nullNode) root=y; 38 else if(x==x->p->left) x->p->left=y; 39 else x->p->right=y; 40 y->left=x; 41 x->p=y; 42 } 43 44 void rightRotate(TreeNode* x) 45 { 46 TreeNode* y=x->left; 47 x->left=y->right; 48 if(y->right!=nullNode) y->right->p=x; 49 y->p=x->p; 50 if(x->p==nullNode) root=y; 51 else if(x==x->p->left) x->p->left=y; 52 else x->p->right=y; 53 y->right=x; 54 x->p=y; 55 } 56 57 58 void transPlant(TreeNode* u,TreeNode*v) 59 { 60 if(u->p==nullNode) root=v; 61 else if(u==u->p->left) u->p->left=v; 62 else u->p->right=v; 63 v->p=u->p; 64 } 65 66 TreeNode* minimum(TreeNode* x) 67 { 68 while(x->left!=nullNode) x=x->left; 69 return x; 70 } 71 72 TreeNode* successor(TreeNode* x) 73 { 74 if(x->right!=nullNode) return minimum(x->right); 75 TreeNode* px=x->p; 76 while(px!=nullNode&&px->right==x) 77 { 78 x=px; 79 px=px->p; 80 } 81 return px; 82 } 83 84 85 86 void insertFix(TreeNode* z) 87 { 88 while(z->p->color==RED) 89 { 90 if(z->p==z->p->p->left) 91 { 92 TreeNode* y=z->p->p->right; 93 if(y->color==RED) 94 { 95 z->p->color=BLACK; 96 y->color=BLACK; 97 z->p->p->color=RED; 98 z=z->p->p; 99 } 100 else 101 { 102 if(z==z->p->right) 103 { 104 z=z->p; 105 leftRotate(z); 106 } 107 z->p->color=BLACK; 108 z->p->p->color=RED; 109 rightRotate(z->p->p); 110 } 111 } 112 else 113 { 114 TreeNode* y=z->p->p->left; 115 if(y->color==RED) 116 { 117 z->p->color=BLACK; 118 y->color=BLACK; 119 z->p->p->color=RED; 120 z=z->p->p; 121 } 122 else 123 { 124 if(z==z->p->left) 125 { 126 z=z->p; 127 rightRotate(z); 128 } 129 z->p->color=BLACK; 130 z->p->p->color=RED; 131 leftRotate(z->p->p); 132 } 133 } 134 } 135 root->color=BLACK; 136 } 137 138 TreeNode* FindNode(int val) 139 { 140 TreeNode* cur=root; 141 while(cur!=nullNode) 142 { 143 if(cur->key==val) return cur; 144 if(cur->key>val) cur=cur->left; 145 else cur=cur->right; 146 } 147 return cur; 148 } 149 150 void removeFix(TreeNode* x) 151 { 152 while(x!=root&&x->color==BLACK) 153 { 154 if(x==x->p->left) 155 { 156 TreeNode* w=x->p->right; 157 if(w->color==RED) 158 { 159 w->color=BLACK; 160 x->p->color=RED; 161 leftRotate(x->p); 162 w=x->p->right; 163 } 164 if(w->left->color==BLACK&&w->right->color==BLACK) 165 { 166 w->color=RED; 167 x=x->p; 168 } 169 else 170 { 171 if(w->right->color==BLACK) 172 { 173 w->left->color=BLACK; 174 w->color=RED; 175 rightRotate(w); 176 w=x->p->right; 177 } 178 w->color=x->p->color; 179 x->p->color=BLACK; 180 w->right->color=BLACK; 181 leftRotate(x->p); 182 x=root; 183 } 184 } 185 else 186 { 187 TreeNode* w=x->p->left; 188 if(w->color==RED) 189 { 190 w->color=BLACK; 191 x->p->color=RED; 192 rightRotate(x->p); 193 w=x->p->left; 194 } 195 if(w->left->color==BLACK&&w->right->color==BLACK) 196 { 197 w->color=RED; 198 x=x->p; 199 } 200 else 201 { 202 if(w->left->color==BLACK) 203 { 204 w->right->color=BLACK; 205 w->color=RED; 206 leftRotate(w); 207 w=x->p->left; 208 } 209 w->color=x->p->color; 210 x->p->color=BLACK; 211 w->left->color=BLACK; 212 rightRotate(x->p); 213 x=root; 214 } 215 } 216 } 217 x->color=BLACK; 218 } 219 220 221 public: 222 223 RedBlackTree() { init(); } 224 225 void init() 226 { 227 nullNode=new TreeNode; 228 nullNode->left=nullNode->right=nullNode->p=nullNode; 229 nullNode->color=BLACK; 230 231 root=nullNode; 232 } 233 234 void insert(int val) 235 { 236 TreeNode* z=NewNode(val); 237 238 TreeNode* y=nullNode; 239 TreeNode* x=root; 240 while(x!=nullNode) 241 { 242 y=x; 243 if(z->key<x->key) x=x->left; 244 else x=x->right; 245 } 246 z->p=y; 247 if(y==nullNode) root=z; 248 else if(z->key<y->key) y->left=z; 249 else y->right=z; 250 z->color=RED; 251 252 insertFix(z); 253 } 254 255 256 void remove(int val) 257 { 258 TreeNode* z=FindNode(val); 259 if(z==nullNode) return; 260 TreeNode* y; 261 TreeNode* x; 262 263 if(z->left==nullNode||z->right==nullNode) y=z; 264 else y=successor(z); 265 266 if(y->left!=nullNode) x=y->left; 267 else x=y->right; 268 269 transPlant(y,x); 270 271 if(y!=z) z->key=y->key; 272 273 if(y->color==BLACK) removeFix(x); 274 delete y; 275 } 276 277 };