红黑树学习笔记(3)-删除操作

时间:2021-07-18 20:46:17

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$是其父节点的右孩子的情况跟这个完全类似)。整个修复过程有四种情况。在修复的过程中,这四种情况之间的转换关系如下图所示:

红黑树学习笔记(3)-删除操作

也就是,如果是情况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$节点都是黑色。

红黑树学习笔记(3)-删除操作

 

情况2:$w$是黑色,$w$的两个孩子都是黑色。注意这时候$x$的父节点的颜色可能是红色也可能是黑色,下图是红色的情况,但是这两种情况执行的操作都是一样的。这时将$w$的颜色置为红色,然后令$x=x的父节点$。

红黑树学习笔记(3)-删除操作

情况3:$w$是黑色,$w$的右孩子是黑色(此时$w$的左孩子一定是红色,否则就是情况2了)。注意这时候$x$的父节点的颜色可能是红色也可能是黑色,下图是红色的情况,但是这两种情况执行的操作都是一样的。如下图所示。这种情况操作之后,将把$w$的右孩子转成红色节点,这也是情况4.现在交换$w$与其左孩子的颜色,然后右旋$w$,最后令$w=x现在的兄弟$

红黑树学习笔记(3)-删除操作

 

情况4:$w$是黑色,$w$的右孩子是红色。注意这时候$x$的父节点的颜色可能是红色也可能是黑色,下图是红色的情况,但是这两种情况执行的操作都是一样的。首先交换$w$与其父节点的颜色,然后置$w$的右孩子为黑色,最后左旋$x$的父节点。这一步之后可结束整个修复过程。

红黑树学习笔记(3)-删除操作

 

  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 };