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