1 /* 2 * rbtree.c -- generic red black tree 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 12 #include <assert.h> 13 #include <stdlib.h> 14 15 #include "rbtree.h" 16 17 #define BLACK 0 18 #define RED 1 19 20 rbnode_type rbtree_null_node = { 21 RBTREE_NULL, /* Parent. */ 22 RBTREE_NULL, /* Left. */ 23 RBTREE_NULL, /* Right. */ 24 NULL, /* Key. */ 25 BLACK /* Color. */ 26 }; 27 28 static void rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node); 29 static void rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node); 30 static void rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node); 31 static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, rbnode_type* child_parent); 32 33 /* 34 * Creates a new red black tree, initializes and returns a pointer to it. 35 * 36 * Return NULL on failure. 37 * 38 */ 39 rbtree_type * 40 rbtree_create (region_type *region, int (*cmpf)(const void *, const void *)) 41 { 42 rbtree_type *rbtree; 43 44 /* Allocate memory for it */ 45 rbtree = (rbtree_type *) region_alloc(region, sizeof(rbtree_type)); 46 if (!rbtree) { 47 return NULL; 48 } 49 50 /* Initialize it */ 51 rbtree->root = RBTREE_NULL; 52 rbtree->count = 0; 53 rbtree->region = region; 54 rbtree->cmp = cmpf; 55 56 return rbtree; 57 } 58 59 /* 60 * Rotates the node to the left. 61 * 62 */ 63 static void 64 rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node) 65 { 66 rbnode_type *right; 67 68 /* Check if rbtree is NULL */ 69 if (!rbtree) { 70 return; 71 } 72 right = node->right; 73 node->right = right->left; 74 if (right->left != RBTREE_NULL) 75 right->left->parent = node; 76 77 right->parent = node->parent; 78 79 if (node->parent != RBTREE_NULL) { 80 if (node == node->parent->left) { 81 node->parent->left = right; 82 } else { 83 node->parent->right = right; 84 } 85 } else { 86 rbtree->root = right; 87 } 88 right->left = node; 89 node->parent = right; 90 } 91 92 /* 93 * Rotates the node to the right. 94 * 95 */ 96 static void 97 rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node) 98 { 99 rbnode_type *left; 100 101 /* Check if rbtree is NULL */ 102 if (!rbtree) { 103 return; 104 } 105 left = node->left; 106 node->left = left->right; 107 if (left->right != RBTREE_NULL) 108 left->right->parent = node; 109 110 left->parent = node->parent; 111 112 if (node->parent != RBTREE_NULL) { 113 if (node == node->parent->right) { 114 node->parent->right = left; 115 } else { 116 node->parent->left = left; 117 } 118 } else { 119 rbtree->root = left; 120 } 121 left->right = node; 122 node->parent = left; 123 } 124 125 static void 126 rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node) 127 { 128 rbnode_type *uncle; 129 130 /* Check if rbtree is NULL */ 131 if (!rbtree) { 132 return; 133 } 134 135 /* While not at the root and need fixing... */ 136 while (node != rbtree->root && node->parent->color == RED) { 137 /* If our parent is left child of our grandparent... */ 138 if (node->parent == node->parent->parent->left) { 139 uncle = node->parent->parent->right; 140 141 /* If our uncle is red... */ 142 if (uncle->color == RED) { 143 /* Paint the parent and the uncle black... */ 144 node->parent->color = BLACK; 145 uncle->color = BLACK; 146 147 /* And the grandparent red... */ 148 node->parent->parent->color = RED; 149 150 /* And continue fixing the grandparent */ 151 node = node->parent->parent; 152 } else { /* Our uncle is black... */ 153 /* Are we the right child? */ 154 if (node == node->parent->right) { 155 node = node->parent; 156 rbtree_rotate_left(rbtree, node); 157 } 158 /* Now we're the left child, repaint and rotate... */ 159 node->parent->color = BLACK; 160 node->parent->parent->color = RED; 161 rbtree_rotate_right(rbtree, node->parent->parent); 162 } 163 } else { 164 uncle = node->parent->parent->left; 165 166 /* If our uncle is red... */ 167 if (uncle->color == RED) { 168 /* Paint the parent and the uncle black... */ 169 node->parent->color = BLACK; 170 uncle->color = BLACK; 171 172 /* And the grandparent red... */ 173 node->parent->parent->color = RED; 174 175 /* And continue fixing the grandparent */ 176 node = node->parent->parent; 177 } else { /* Our uncle is black... */ 178 /* Are we the right child? */ 179 if (node == node->parent->left) { 180 node = node->parent; 181 rbtree_rotate_right(rbtree, node); 182 } 183 /* Now we're the right child, repaint and rotate... */ 184 node->parent->color = BLACK; 185 node->parent->parent->color = RED; 186 rbtree_rotate_left(rbtree, node->parent->parent); 187 } 188 } 189 } 190 rbtree->root->color = BLACK; 191 } 192 193 194 /* 195 * Inserts a node into a red black tree. 196 * 197 * Returns NULL on failure or the pointer to the newly added node 198 * otherwise. 199 */ 200 rbnode_type * 201 rbtree_insert (rbtree_type *rbtree, rbnode_type *data) 202 { 203 /* XXX Not necessary, but keeps compiler quiet... */ 204 int r = 0; 205 rbnode_type *node; 206 rbnode_type *parent; 207 208 /* Check if rbtree is NULL */ 209 if (!rbtree) { 210 return NULL; 211 } 212 213 /* We start at the root of the tree */ 214 node = rbtree->root; 215 parent = RBTREE_NULL; 216 217 /* Lets find the new parent... */ 218 while (node != RBTREE_NULL) { 219 /* Compare two keys, do we have a duplicate? */ 220 if ((r = rbtree->cmp(data->key, node->key)) == 0) { 221 return NULL; 222 } 223 parent = node; 224 225 if (r < 0) { 226 node = node->left; 227 } else { 228 node = node->right; 229 } 230 } 231 232 /* Initialize the new node */ 233 data->parent = parent; 234 data->left = data->right = RBTREE_NULL; 235 data->color = RED; 236 rbtree->count++; 237 238 /* Insert it into the tree... */ 239 if (parent != RBTREE_NULL) { 240 if (r < 0) { 241 parent->left = data; 242 } else { 243 parent->right = data; 244 } 245 } else { 246 rbtree->root = data; 247 } 248 249 /* Fix up the red-black properties... */ 250 rbtree_insert_fixup(rbtree, data); 251 252 return data; 253 } 254 255 /* 256 * Searches the red black tree, returns the data if key is found or NULL otherwise. 257 * 258 */ 259 rbnode_type * 260 rbtree_search (rbtree_type *rbtree, const void *key) 261 { 262 rbnode_type *node; 263 264 /* Check if rbtree is NULL */ 265 if (!rbtree) { 266 return NULL; 267 } 268 269 if (rbtree_find_less_equal(rbtree, key, &node)) { 270 return node; 271 } else { 272 return NULL; 273 } 274 } 275 276 /* helpers for delete */ 277 static void swap_int8(uint8_t* x, uint8_t* y) 278 { 279 uint8_t t = *x; *x = *y; *y = t; 280 } 281 282 static void swap_np(rbnode_type** x, rbnode_type** y) 283 { 284 rbnode_type* t = *x; *x = *y; *y = t; 285 } 286 287 static void change_parent_ptr(rbtree_type* rbtree, rbnode_type* parent, rbnode_type* old, rbnode_type* new) 288 { 289 /* Check if rbtree is NULL */ 290 if (!rbtree) { 291 return; 292 } 293 294 if(parent == RBTREE_NULL) 295 { 296 assert(rbtree->root == old); 297 if(rbtree->root == old) rbtree->root = new; 298 return; 299 } 300 assert(parent->left == old || parent->right == old 301 || parent->left == new || parent->right == new); 302 if(parent->left == old) parent->left = new; 303 if(parent->right == old) parent->right = new; 304 } 305 static void change_child_ptr(rbnode_type* child, rbnode_type* old, rbnode_type* new) 306 { 307 if(child == RBTREE_NULL) return; 308 assert(child->parent == old || child->parent == new); 309 if(child->parent == old) child->parent = new; 310 } 311 312 rbnode_type* 313 rbtree_delete(rbtree_type *rbtree, const void *key) 314 { 315 rbnode_type *to_delete; 316 rbnode_type *child; 317 318 /* Check if rbtree is NULL */ 319 if (!rbtree) { 320 return NULL; 321 } 322 323 if((to_delete = rbtree_search(rbtree, key)) == 0) return 0; 324 rbtree->count--; 325 326 /* make sure we have at most one non-leaf child */ 327 if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL) 328 { 329 /* swap with smallest from right subtree (or largest from left) */ 330 rbnode_type *smright = to_delete->right; 331 while(smright->left != RBTREE_NULL) 332 smright = smright->left; 333 /* swap the smright and to_delete elements in the tree, 334 * but the rbnode_type is first part of user data struct 335 * so cannot just swap the keys and data pointers. Instead 336 * readjust the pointers left,right,parent */ 337 338 /* swap colors - colors are tied to the position in the tree */ 339 swap_int8(&to_delete->color, &smright->color); 340 341 /* swap child pointers in parents of smright/to_delete */ 342 change_parent_ptr(rbtree, to_delete->parent, to_delete, smright); 343 if(to_delete->right != smright) 344 change_parent_ptr(rbtree, smright->parent, smright, to_delete); 345 346 /* swap parent pointers in children of smright/to_delete */ 347 change_child_ptr(smright->left, smright, to_delete); 348 change_child_ptr(smright->left, smright, to_delete); 349 change_child_ptr(smright->right, smright, to_delete); 350 change_child_ptr(smright->right, smright, to_delete); 351 change_child_ptr(to_delete->left, to_delete, smright); 352 if(to_delete->right != smright) 353 change_child_ptr(to_delete->right, to_delete, smright); 354 if(to_delete->right == smright) 355 { 356 /* set up so after swap they work */ 357 to_delete->right = to_delete; 358 smright->parent = smright; 359 } 360 361 /* swap pointers in to_delete/smright nodes */ 362 swap_np(&to_delete->parent, &smright->parent); 363 swap_np(&to_delete->left, &smright->left); 364 swap_np(&to_delete->right, &smright->right); 365 366 /* now delete to_delete (which is at the location where the smright previously was) */ 367 } 368 assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL); 369 370 if(to_delete->left != RBTREE_NULL) child = to_delete->left; 371 else child = to_delete->right; 372 373 /* unlink to_delete from the tree, replace to_delete with child */ 374 change_parent_ptr(rbtree, to_delete->parent, to_delete, child); 375 change_child_ptr(child, to_delete, to_delete->parent); 376 377 if(to_delete->color == RED) 378 { 379 /* if node is red then the child (black) can be swapped in */ 380 } 381 else if(child->color == RED) 382 { 383 /* change child to BLACK, removing a RED node is no problem */ 384 if(child!=RBTREE_NULL) child->color = BLACK; 385 } 386 else rbtree_delete_fixup(rbtree, child, to_delete->parent); 387 388 /* unlink completely */ 389 to_delete->parent = RBTREE_NULL; 390 to_delete->left = RBTREE_NULL; 391 to_delete->right = RBTREE_NULL; 392 to_delete->color = BLACK; 393 return to_delete; 394 } 395 396 static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, rbnode_type* child_parent) 397 { 398 rbnode_type* sibling; 399 int go_up = 1; 400 401 /* Check if rbtree is NULL */ 402 if (!rbtree) { 403 return; 404 } 405 406 /* determine sibling to the node that is one-black short */ 407 if(child_parent->right == child) sibling = child_parent->left; 408 else sibling = child_parent->right; 409 410 while(go_up) 411 { 412 if(child_parent == RBTREE_NULL) 413 { 414 /* removed parent==black from root, every path, so ok */ 415 return; 416 } 417 418 if(sibling->color == RED) 419 { /* rotate to get a black sibling */ 420 child_parent->color = RED; 421 sibling->color = BLACK; 422 if(child_parent->right == child) 423 rbtree_rotate_right(rbtree, child_parent); 424 else rbtree_rotate_left(rbtree, child_parent); 425 /* new sibling after rotation */ 426 if(child_parent->right == child) sibling = child_parent->left; 427 else sibling = child_parent->right; 428 } 429 430 if(child_parent->color == BLACK 431 && sibling->color == BLACK 432 && sibling->left->color == BLACK 433 && sibling->right->color == BLACK) 434 { /* fixup local with recolor of sibling */ 435 if(sibling != RBTREE_NULL) 436 sibling->color = RED; 437 438 child = child_parent; 439 child_parent = child_parent->parent; 440 /* prepare to go up, new sibling */ 441 if(child_parent->right == child) sibling = child_parent->left; 442 else sibling = child_parent->right; 443 } 444 else go_up = 0; 445 } 446 447 if(child_parent->color == RED 448 && sibling->color == BLACK 449 && sibling->left->color == BLACK 450 && sibling->right->color == BLACK) 451 { 452 /* move red to sibling to rebalance */ 453 if(sibling != RBTREE_NULL) 454 sibling->color = RED; 455 child_parent->color = BLACK; 456 return; 457 } 458 assert(sibling != RBTREE_NULL); 459 460 /* get a new sibling, by rotating at sibling. See which child 461 of sibling is red */ 462 if(child_parent->right == child 463 && sibling->color == BLACK 464 && sibling->right->color == RED 465 && sibling->left->color == BLACK) 466 { 467 sibling->color = RED; 468 sibling->right->color = BLACK; 469 rbtree_rotate_left(rbtree, sibling); 470 /* new sibling after rotation */ 471 if(child_parent->right == child) sibling = child_parent->left; 472 else sibling = child_parent->right; 473 } 474 else if(child_parent->left == child 475 && sibling->color == BLACK 476 && sibling->left->color == RED 477 && sibling->right->color == BLACK) 478 { 479 sibling->color = RED; 480 sibling->left->color = BLACK; 481 rbtree_rotate_right(rbtree, sibling); 482 /* new sibling after rotation */ 483 if(child_parent->right == child) sibling = child_parent->left; 484 else sibling = child_parent->right; 485 } 486 487 /* now we have a black sibling with a red child. rotate and exchange colors. */ 488 sibling->color = child_parent->color; 489 child_parent->color = BLACK; 490 if(child_parent->right == child) 491 { 492 assert(sibling->left->color == RED); 493 sibling->left->color = BLACK; 494 rbtree_rotate_right(rbtree, child_parent); 495 } 496 else 497 { 498 assert(sibling->right->color == RED); 499 sibling->right->color = BLACK; 500 rbtree_rotate_left(rbtree, child_parent); 501 } 502 } 503 504 int 505 rbtree_find_less_equal(rbtree_type *rbtree, const void *key, rbnode_type **result) 506 { 507 int r; 508 rbnode_type *node; 509 510 assert(result); 511 512 /* Check if rbtree is NULL */ 513 if (!rbtree) { 514 *result = NULL; 515 return 0; 516 } 517 518 /* We start at root... */ 519 node = rbtree->root; 520 521 *result = NULL; 522 523 /* While there are children... */ 524 while (node != RBTREE_NULL) { 525 r = rbtree->cmp(key, node->key); 526 if (r == 0) { 527 /* Exact match */ 528 *result = node; 529 return 1; 530 } 531 if (r < 0) { 532 node = node->left; 533 } else { 534 /* Temporary match */ 535 *result = node; 536 node = node->right; 537 } 538 } 539 return 0; 540 } 541 542 /* 543 * Finds the first element in the red black tree 544 * 545 */ 546 rbnode_type * 547 rbtree_first (rbtree_type *rbtree) 548 { 549 rbnode_type *node; 550 551 /* Check if rbtree is NULL */ 552 if (!rbtree) { 553 return NULL; 554 } 555 556 for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left); 557 return node; 558 } 559 560 rbnode_type * 561 rbtree_last (rbtree_type *rbtree) 562 { 563 rbnode_type *node; 564 565 /* Check if rbtree is NULL */ 566 if (!rbtree) { 567 return NULL; 568 } 569 570 for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right); 571 return node; 572 } 573 574 /* 575 * Returns the next node... 576 * 577 */ 578 rbnode_type * 579 rbtree_next (rbnode_type *node) 580 { 581 rbnode_type *parent; 582 583 if (node->right != RBTREE_NULL) { 584 /* One right, then keep on going left... */ 585 for (node = node->right; node->left != RBTREE_NULL; node = node->left); 586 } else { 587 parent = node->parent; 588 while (parent != RBTREE_NULL && node == parent->right) { 589 node = parent; 590 parent = parent->parent; 591 } 592 node = parent; 593 } 594 return node; 595 } 596 597 rbnode_type * 598 rbtree_previous(rbnode_type *node) 599 { 600 rbnode_type *parent; 601 602 if (node->left != RBTREE_NULL) { 603 /* One left, then keep on going right... */ 604 for (node = node->left; node->right != RBTREE_NULL; node = node->right); 605 } else { 606 parent = node->parent; 607 while (parent != RBTREE_NULL && node == parent->left) { 608 node = parent; 609 parent = parent->parent; 610 } 611 node = parent; 612 } 613 return node; 614 } 615