这一章节特别有意思。习题也比较多,但是很容易掌握。主要描述的就是在已知数据结构的基础上,通过增加或修改部分基础操作。来构造更加有效的新数据结构。

14.1 动态数据统计
本节主要介绍如何修改红黑树,使得可以在O(lgn)时间内确定顺序统计量,如何在O(lgn)时间内确定一个元素的秩,即它在集合线性序中的位置。顺序统计树(order-static tree)T只是简单地在每个结点上存储附加信息的一棵红黑树,附加信息是当前子树的size大小。源代码如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 #define LOCAL_DEBUG
  9 #define RED        true
 10 #define BLACK    false
 11 
 12 typedef struct Node_t {
 13     bool color;
 14     int key, size;
 15     Node_t *p, *left, *right;
 16     Node_t() {}
 17     Node_t(int kkey) {
 18         key = kkey;
 19     }
 20 } Node_t;
 21 
 22 typedef struct Tree_t {
 23     Node_t *NIL;
 24     Node_t *root;
 25     Tree_t() {
 26         NIL = new Node_t();
 27         NIL->key = 0;
 28         NIL->size = 0;
 29         NIL->color = BLACK;
 30         NIL->p = NIL->left = NIL->right = NIL;
 31         root = NIL;
 32     }
 33 } Tree_t;
 34 
 35 Tree_t *t;
 36 
 37 void Inorder_RBTree_Walk(Tree_t *t, Node_t *x) {
 38     if (x != t->NIL) {
 39         Inorder_RBTree_Walk(t, x->left);
 40         printf("key: %d, size: %d\n", x->key, x->size);
 41         Inorder_RBTree_Walk(t, x->right);
 42     }
 43 }
 44 
 45 void Preorder_RBTree_Walk(Tree_t *t, Node_t *x) {
 46     if (x != t->NIL) {
 47         printf("key: %d, size: %d\n", x->key, x->size);
 48         Preorder_RBTree_Walk(t, x->left);
 49         Preorder_RBTree_Walk(t, x->right);
 50     }
 51 }
 52 
 53 void Postorder_RBTree_Walk(Tree_t *t, Node_t *x) {
 54     if (x != t->NIL) {
 55         Postorder_RBTree_Walk(t, x->left);
 56         Postorder_RBTree_Walk(t, x->right);
 57         printf("key: %d, size: %d\n", x->key, x->size);
 58     }
 59 }
 60 
 61 void Inorder_RBTree_Walk_WithColor(Tree_t *t, Node_t *x) {
 62     if (x != t->NIL) {
 63         Inorder_RBTree_Walk_WithColor(t, x->left);
 64         printf("key: %d, size: %d, color: %s\n", x->key, x->size, x->color?"Red":"Black");
 65         Inorder_RBTree_Walk_WithColor(t, x->right);
 66     }
 67 }
 68 
 69 void Preorder_RBTree_Walk_WithColor(Tree_t *t, Node_t *x) {
 70     if (x != t->NIL) {
 71         printf("key: %d, size: %d, color: %s\n", x->key, x->size, x->color?"Red":"Black");
 72         Preorder_RBTree_Walk_WithColor(t, x->left);
 73         Preorder_RBTree_Walk_WithColor(t, x->right);
 74     }
 75 }
 76 
 77 void Postorder_RBTree_Walk_WithColor(Tree_t *t, Node_t *x) {
 78     if (x != t->NIL) {
 79         Postorder_RBTree_Walk_WithColor(t, x->left);
 80         Postorder_RBTree_Walk_WithColor(t, x->right);
 81         printf("key: %d, size: %d, color: %s\n", x->key, x->size, x->color?"Red":"Black");
 82     }
 83 }
 84 
 85 Node_t *RBTree_Minimum(Tree_t *t, Node_t *x) {
 86     while (x->left != t->NIL)
 87         x = x->left;
 88     return x;
 89 }
 90 
 91 Node_t *RBTree_Maximum(Tree_t *t, Node_t *x) {
 92     while (x->right != t->NIL)
 93         x = x->right;
 94     return x;
 95 }
 96 
 97 Node_t *RBTree_Search(Tree_t *t, int key) {
 98     Node_t *x = t->root;
 99     while (x!=t->NIL && x->key!=key) {
100         if (key < x->key) {
101             x = x->left;
102         } else {
103             x = x->right;
104         }
105     }
106     return x;
107 }
108 
109 void Left_Rotate(Tree_t *t, Node_t *x) {
110     Node_t *y = x->right;
111     x->right = y->left;
112     if (y->left != t->NIL)
113         y->left->p = x;
114     y->p = x->p;
115     if (x->p == t->NIL) {
116         // x is root
117         t->root = y;    
118     } else if (x == x->p->left) {
119         x->p->left = y;
120     } else {
121         x->p->right = y;
122     }
123     y->left = x;
124     x->p = y;
125     y->size = x->size;
126     x->size = x->left->size + x->right->size + 1;
127 }
128 
129 void Right_Rotate(Tree_t *t, Node_t *y) {
130     Node_t *x = y->left;
131     y->left = x->right;
132     if (x->right != t->NIL)
133         x->right->p = y;
134     x->p = y->p;
135     if (y->p == t->NIL) {
136         // y is root
137         t->root = x;
138     } else if (y == y->p->left) {
139         y->p->left = x;
140     } else {
141         y->p->right = x;
142     }
143     x->right = y;
144     y->p = x;
145     x->size = y->size;
146     y->size = y->left->size + y->right->size + 1;
147 }
148 
149 void RBTree_Transplant(Tree_t *t, Node_t *u, Node_t *v) {
150     if (u->p == t->NIL) {
151         t->root = v;
152     } else if (u == u->p->left) {
153         u->p->left = v;
154     } else {
155         u->p->right = v;
156     }
157     v->p = u->p;
158 }
159 
160 void RBTree_Insert_Fixup(Tree_t *t, Node_t *z) {
161     Node_t *y;
162     
163     while (z->p->color == RED) {
164         // means z->p->p->color == BLACK
165         if (z->p == z->p->p->left) {
166             y = z->p->p->right;
167             if (y->color == RED) {
168                 z->p->color = BLACK;
169                 y->color = BLACK;
170                 z->p->p->color = RED;
171                 z = z->p->p;
172             } else {
173                 // y->color is BLACK
174                 if (z == z->p->right) {
175                     z = z->p;
176                     Left_Rotate(t, z);
177                 }
178                 z->p->color = BLACK;    // break later
179                 z->p->p->color = RED;
180                 Right_Rotate(t, z->p->p);
181             }
182         } else {
183             y = z->p->p->left;
184             if (y->color == RED) {
185                 z->p->color = BLACK;
186                 y->color = BLACK;
187                 z->p->p->color = RED;
188                 z = z->p->p;
189             } else {
190                 // y->color is BLACK
191                 if (z == z->p->left) {
192                     z = z->p;
193                     Right_Rotate(t, z);
194                 }
195                 z->p->color = BLACK;    // break later
196                 z->p->p->color = RED;
197                 Left_Rotate(t, z->p->p);
198             }
199         }
200     }
201     t->root->color = BLACK;
202 }
203 
204 void RBTree_Insert(Tree_t *t, Node_t *z) {
205     Node_t *y = t->NIL;
206     Node_t *x = t->root;
207     while (x != t->NIL) {
208         y = x;
209         ++x->size;
210         if (z->key < x->key) {
211             x = x->left;
212         } else {
213             x = x->right;
214         }
215     }
216     z->p = y;
217     if (y == t->NIL) {
218         // tree is empty
219         t->root = z;
220     } else if (z->key < y->key) {
221         y->left = z;
222     } else {
223         y->right = z;
224     }
225     z->left = z->right = t->NIL;
226     z->color = RED;
227     z->size = 1;
228     RBTree_Insert_Fixup(t, z);
229 }
230 
231 void RBTree_Delete_Fixup(Tree_t *t, Node_t *x) {
232     Node_t *w;
233     
234     while (x!=t->root && x->color==BLACK) {
235         if (x == x->p->left) {
236             w = x->p->right;
237             if (w->color == RED) {
238                 w->color = BLACK;
239                 x->p->color = RED;
240                 Left_Rotate(t, x->p);
241                 w = x->p->right;
242             }
243             // means w->color == BLACK
244             if (w->left->color==BLACK && w->right->color==BLACK) {
245                 w->color = RED;
246                 x = x->p;    // fetch the black in w & x and pass it to x->p
247             } else {
248                 if (w->right->color == BLACK) {
249                     // means w->left->color == RED
250                     w->left->color = BLACK;
251                     w->color = RED;
252                     Right_Rotate(t, w);
253                     w = x->p->right;
254                 }
255                 // means w->right->color == RED && w->left->color == uncertain
256                 w->color = x->p->color;
257                 x->p->color = BLACK;
258                 w->right->color = BLACK;
259                 Left_Rotate(t, x->p);
260                 x = t->root;
261             }
262         } else {
263             w = x->p->left;
264             if (w->color == RED) {
265                 w->color = BLACK;
266                 x->p->color = RED;
267                 Right_Rotate(t, x->p);
268                 w = x->p->left;
269             }
270             // means w->color == BLACK
271             if (w->left->color==BLACK && w->right->color==BLACK) {
272                 w->color = RED;
273                 x = x->p; // fetch the black in w & x and pass it to x->p
274             } else {
275                 if (w->left->color == BLACK) {
276                     // means x->right->color == RED
277                     w->right->color = BLACK;
278                     w->color = RED;
279                     Left_Rotate(t, w);
280                     w = x->p->left;
281                 }
282                 // means w->left->color == RED && w->right->color = ANY
283                 w->color = x->p->color;
284                 x->p->color = BLACK;
285                 w->left->color = BLACK;
286                 Right_Rotate(t, x->p);
287                 x = t->root;
288             }
289         }
290     }
291     x->color = BLACK;
292 }
293 
294 void RBTree_Delete(Tree_t *t, Node_t *z) {
295     Node_t *x, *y = z;
296     Node_t *q;    // q used to back trace for maintening the [size] of Node_t
297     bool y_original_color = y->color;
298     
299     if (z->left == t->NIL) {
300         x = z->right;
301         q = y->p;
302         RBTree_Transplant(t, y, x);
303     } else if (z->right == t->NIL) {
304         x = z->left;
305         RBTree_Transplant(t, y, x);
306         q = y->p;
307     } else {
308         y = RBTree_Minimum(t, z->right);
309         y_original_color = y->color;
310         x = y->right;
311         if (y->p == z) {
312             x->p = y;
313             q = y;
314         } else {
315             RBTree_Transplant(t, y, x);
316             q = y->p;
317             y->right = z->right;
318             y->right->p = y;
319         }
320         RBTree_Transplant(t, z, y);
321         y->left = z->left;
322         y->left->p = y;
323         y->color = z->color;
324         y->size = z->size;
325     }
326     
327     // maintence the [size] of Node_t
328     while (q != t->NIL) {
329         --q->size;
330         printf("key=%d,size=%d, --\n", q->key, q->size);
331         q = q->p;
332     }
333     
334     if (y_original_color == BLACK)
335         RBTree_Delete_Fixup(t, x);    // use x replace y
336 }
337 
338 int check_BHeight(Tree_t *t, Node_t *x, bool &f) {
339     if (x == t->NIL)
340         return 1;
341     int lBH = check_BHeight(t, x->left, f);
342     int rBH = check_BHeight(t, x->right, f);
343     
344     if (f == false)
345         return 0;
346     
347     if (lBH != rBH)
348         f = false;
349     if (x->color == BLACK)
350         return lBH+1;
351     return lBH;
352 }
353 
354 bool check_RNode(Tree_t *t, Node_t *x) {
355     if (x == t->NIL)
356         return true;
357     if (x->color==RED && (x->left->color!=BLACK || x->right->color!=BLACK)) {
358         return false;
359     }
360     return check_RNode(t, x->left) && check_RNode(t, x->right);
361 }
362 
363 bool check_Size(Tree_t *t, Node_t *x) {
364     if (x == t->NIL) {
365         return x->size == 0;
366     }
367     
368     if (x->left->size+x->right->size+1 != x->size) {
369         printf("check_size: key=%d, size=%d, wrong!!!\n", x->key, x->size);
370         printf("x->left: key=%d, size=%d\n", x->left->key, x->left->size);
371         printf("x->right: key=%d, size=%d\n", x->right->key, x->right->size);
372         return false;
373     }
374     return check_Size(t, x->left) && check_Size(t, x->right) && x->left->size+x->right->size+1==x->size;
375 }
376 
377 bool check_RBTree(Tree_t *t) {
378     bool ret = true;
379     
380     if (t->NIL->color != BLACK)
381         return false;
382     if (t->root == t->NIL)
383         return ret;
384     if (t->root->color != BLACK)
385         return false;
386     
387     ret = check_RNode(t, t->root);
388     if (ret == false) {
389         puts("not fit B<-R->B");
390         return false;
391     }
392     
393     ret = check_Size(t, t->root);
394     if (ret == false) {
395         puts("size not fit");
396         return false;
397     }
398     
399     check_BHeight(t, t->root, ret);
400     if (ret == false)
401         puts("BHeight not fit");
402     
403     return ret;
404 }
405 
406 Node_t *OS_Select(Tree_t *t, Node_t *x, int i) {
407     int r = x->left->size + 1;
408     if (r == i)
409         return x;
410     else if (r > i)
411         return OS_Select(t, x->left, i);
412     else
413         return OS_Select(t, x->right, i-r);
414 }
415 
416 int OS_Rank(Tree_t *t, Node_t *x) {
417     int r = x->left->size + 1;
418     Node_t *y = x;
419     while (y != t->root) {
420         if (y == y->p->right)
421             r += y->p->left->size + 1;
422         y = y->p;
423     }
424     return r;
425 }
426 
427 void init() {
428     t = new Tree_t();
429     int a[] = {26, 17, 41, 14, 21, 30, 47, 10, 16, 19, 21, 28, 38, 7, 12, 14, 20, 35, 39, 3};
430     int n = sizeof(a) / sizeof(int);
431     Node_t *p;
432     
433     printf("n = %d\n", n);
434     for (int i=0; i<n; ++i) {
435         p = new Node_t(a[i]);
436         RBTree_Insert(t, p);
437     }
438     
439     Inorder_RBTree_Walk_WithColor(t, t->root);
440     if (check_RBTree(t))
441         puts("Right");
442     else
443         puts("Wrong");
444     printf("\n");
445 }
446 
447 void test_delete() {
448     Tree_t *t = new Tree_t();
449     int a[] = {26, 17, 41, 14, 21, 30, 47, 10, 16, 19, 21, 28, 38, 7, 12, 14, 20, 35, 39, 3};
450     int n = sizeof(a) / sizeof(int);
451     bool visit[30];
452     int i, j, k;
453     Node_t *p;
454     
455     printf("n = %d\n", n);
456     for (i=0; i<n; ++i) {
457         p = new Node_t(a[i]);
458         RBTree_Insert(t, p);
459     }
460     
461     memset(visit, false, sizeof(visit));
462     for (i=0; i<n; ++i) {
463         while (1) {
464             j = rand()%n;
465             if (visit[j] == false)
466                 break;
467         }
468         visit[j] = true;
469         p = RBTree_Search(t, a[j]);
470         printf("delete %d\n", a[j]);
471         RBTree_Delete(t, p);
472         Inorder_RBTree_Walk_WithColor(t, t->root);
473         if (check_RBTree(t))
474             puts("Right");
475         else
476             puts("Wrong");
477         RBTree_Insert(t, p);
478         if (check_RBTree(t))
479             puts("Right");
480         else
481             puts("Wrong");
482         printf("\n\n\n");
483     }
484 }
485 
486 int main() {
487     
488     #ifdef LOCAL_DEBUG
489         freopen("data.in", "r", stdin);
490         freopen("data.out", "w", stdout);
491     #endif
492     
493     //init();
494     test_delete();
495     
496     return 0;
497 }
View Code

相关文章: