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