1 /* 2 * ctrees.c 3 * 4 * Author: mozman 5 * Copyright (c) 2010-2013 by Manfred Moitzi 6 * License: MIT-License 7 */ 8 9 #include "ctrees.h" 10 #include "stack.h" 11 #include <Python.h> 12 13 #define LEFT 0 14 #define RIGHT 1 15 #define KEY(node) (node->key) 16 #define VALUE(node) (node->value) 17 #define LEFT_NODE(node) (node->link[LEFT]) 18 #define RIGHT_NODE(node) (node->link[RIGHT]) 19 #define LINK(node, dir) (node->link[dir]) 20 #define XDATA(node) (node->xdata) 21 #define RED(node) (node->xdata) 22 #define BALANCE(node) (node->xdata) 23 24 static node_t * 25 ct_new_node(PyObject *key, PyObject *value, int xdata) 26 { 27 node_t *new_node = PyMem_Malloc(sizeof(node_t)); 28 if (new_node != NULL) { 29 KEY(new_node) = key; 30 Py_INCREF(key); 31 VALUE(new_node) = value; 32 Py_INCREF(value); 33 LEFT_NODE(new_node) = NULL; 34 RIGHT_NODE(new_node) = NULL; 35 XDATA(new_node) = xdata; 36 } 37 return new_node; 38 } 39 40 static void 41 ct_delete_node(node_t *node) 42 { 43 if (node != NULL) { 44 Py_XDECREF(KEY(node)); 45 Py_XDECREF(VALUE(node)); 46 LEFT_NODE(node) = NULL; 47 RIGHT_NODE(node) = NULL; 48 PyMem_Free(node); 49 } 50 } 51 52 extern void 53 ct_delete_tree(node_t *root) 54 { 55 if (root == NULL) 56 return; 57 if (LEFT_NODE(root) != NULL) { 58 ct_delete_tree(LEFT_NODE(root)); 59 } 60 if (RIGHT_NODE(root) != NULL) { 61 ct_delete_tree(RIGHT_NODE(root)); 62 } 63 ct_delete_node(root); 64 } 65 66 static void 67 ct_swap_data(node_t *node1, node_t *node2) 68 { 69 PyObject *tmp; 70 tmp = KEY(node1); 71 KEY(node1) = KEY(node2); 72 KEY(node2) = tmp; 73 tmp = VALUE(node1); 74 VALUE(node1) = VALUE(node2); 75 VALUE(node2) = tmp; 76 } 77 78 int 79 ct_compare(PyObject *key1, PyObject *key2) 80 { 81 int res; 82 83 res = PyObject_RichCompareBool(key1, key2, Py_LT); 84 if (res > 0) 85 return -1; 86 else if (res < 0) { 87 PyErr_SetString(PyExc_TypeError, "invalid type for key"); 88 return 0; 89 } 90 /* second compare: 91 +1 if key1 > key2 92 0 if not -> equal 93 -1 means error, if error, it should happend at the first compare 94 */ 95 return PyObject_RichCompareBool(key1, key2, Py_GT); 96 } 97 98 extern node_t * 99 ct_find_node(node_t *root, PyObject *key) 100 { 101 int res; 102 while (root != NULL) { 103 res = ct_compare(key, KEY(root)); 104 if (res == 0) /* key found */ 105 return root; 106 else { 107 root = LINK(root, (res > 0)); 108 } 109 } 110 return NULL; /* key not found */ 111 } 112 113 extern PyObject * 114 ct_get_item(node_t *root, PyObject *key) 115 { 116 node_t *node; 117 PyObject *tuple; 118 119 node = ct_find_node(root, key); 120 if (node != NULL) { 121 tuple = PyTuple_New(2); 122 PyTuple_SET_ITEM(tuple, 0, KEY(node)); 123 PyTuple_SET_ITEM(tuple, 1, VALUE(node)); 124 return tuple; 125 } 126 Py_RETURN_NONE; 127 } 128 129 extern node_t * 130 ct_max_node(node_t *root) 131 /* get node with largest key */ 132 { 133 if (root == NULL) 134 return NULL; 135 while (RIGHT_NODE(root) != NULL) 136 root = RIGHT_NODE(root); 137 return root; 138 } 139 140 extern node_t * 141 ct_min_node(node_t *root) 142 // get node with smallest key 143 { 144 if (root == NULL) 145 return NULL; 146 while (LEFT_NODE(root) != NULL) 147 root = LEFT_NODE(root); 148 return root; 149 } 150 151 extern int 152 ct_bintree_remove(node_t **rootaddr, PyObject *key) 153 /* attention: rootaddr is the address of the root pointer */ 154 { 155 node_t *node, *parent, *replacement; 156 int direction, cmp_res, down_dir; 157 158 node = *rootaddr; 159 160 if (node == NULL) 161 return 0; /* root is NULL */ 162 parent = NULL; 163 direction = 0; 164 165 while (1) { 166 cmp_res = ct_compare(key, KEY(node)); 167 if (cmp_res == 0) /* key found, remove node */ 168 { 169 if ((LEFT_NODE(node) != NULL) && (RIGHT_NODE(node) != NULL)) { 170 /* find replacement node: smallest key in right-subtree */ 171 parent = node; 172 direction = RIGHT; 173 replacement = RIGHT_NODE(node); 174 while (LEFT_NODE(replacement) != NULL) { 175 parent = replacement; 176 direction = LEFT; 177 replacement = LEFT_NODE(replacement); 178 } 179 LINK(parent, direction) = RIGHT_NODE(replacement); 180 /* swap places */ 181 ct_swap_data(node, replacement); 182 node = replacement; /* delete replacement node */ 183 } 184 else { 185 down_dir = (LEFT_NODE(node) == NULL) ? RIGHT : LEFT; 186 if (parent == NULL) /* root */ 187 { 188 *rootaddr = LINK(node, down_dir); 189 } 190 else { 191 LINK(parent, direction) = LINK(node, down_dir); 192 } 193 } 194 ct_delete_node(node); 195 return 1; /* remove was success full */ 196 } 197 else { 198 direction = (cmp_res < 0) ? LEFT : RIGHT; 199 parent = node; 200 node = LINK(node, direction); 201 if (node == NULL) 202 return 0; /* error key not found */ 203 } 204 } 205 } 206 207 extern int 208 ct_bintree_insert(node_t **rootaddr, PyObject *key, PyObject *value) 209 /* attention: rootaddr is the address of the root pointer */ 210 { 211 node_t *parent, *node; 212 int direction, cval; 213 node = *rootaddr; 214 if (node == NULL) { 215 node = ct_new_node(key, value, 0); /* new node is also the root */ 216 if (node == NULL) 217 return -1; /* got no memory */ 218 *rootaddr = node; 219 } 220 else { 221 direction = LEFT; 222 parent = NULL; 223 while (1) { 224 if (node == NULL) { 225 node = ct_new_node(key, value, 0); 226 if (node == NULL) 227 return -1; /* get no memory */ 228 LINK(parent, direction) = node; 229 return 1; 230 } 231 cval = ct_compare(key, KEY(node)); 232 if (cval == 0) { 233 /* key exists, replace value object */ 234 Py_XDECREF(VALUE(node)); /* release old value object */ 235 VALUE(node) = value; /* set new value object */ 236 Py_INCREF(value); /* take new value object */ 237 return 0; 238 } 239 else { 240 parent = node; 241 direction = (cval < 0) ? LEFT : RIGHT; 242 node = LINK(node, direction); 243 } 244 } 245 } 246 return 1; 247 } 248 249 static int 250 is_red (node_t *node) 251 { 252 return (node != NULL) && (RED(node) == 1); 253 } 254 255 #define rb_new_node(key, value) ct_new_node(key, value, 1) 256 257 static node_t * 258 rb_single(node_t *root, int dir) 259 { 260 node_t *save = root->link[!dir]; 261 262 root->link[!dir] = save->link[dir]; 263 save->link[dir] = root; 264 265 RED(root) = 1; 266 RED(save) = 0; 267 return save; 268 } 269 270 static node_t * 271 rb_double(node_t *root, int dir) 272 { 273 root->link[!dir] = rb_single(root->link[!dir], !dir); 274 return rb_single(root, dir); 275 } 276 277 #define rb_new_node(key, value) ct_new_node(key, value, 1) 278 279 extern int 280 rb_insert(node_t **rootaddr, PyObject *key, PyObject *value) 281 { 282 node_t *root = *rootaddr; 283 284 if (root == NULL) { 285 /* 286 We have an empty tree; attach the 287 new node directly to the root 288 */ 289 root = rb_new_node(key, value); 290 if (root == NULL) 291 return -1; // got no memory 292 } 293 else { 294 node_t head; /* False tree root */ 295 node_t *g, *t; /* Grandparent & parent */ 296 node_t *p, *q; /* Iterator & parent */ 297 int dir = 0; 298 int last = 0; 299 int new_node = 0; 300 301 /* Set up our helpers */ 302 t = &head; 303 g = NULL; 304 p = NULL; 305 RIGHT_NODE(t) = root; 306 LEFT_NODE(t) = NULL; 307 q = RIGHT_NODE(t); 308 309 /* Search down the tree for a place to insert */ 310 for (;;) { 311 int cmp_res; 312 if (q == NULL) { 313 /* Insert a new node at the first null link */ 314 q = rb_new_node(key, value); 315 p->link[dir] = q; 316 new_node = 1; 317 if (q == NULL) 318 return -1; // get no memory 319 } 320 else if (is_red(q->link[0]) && is_red(q->link[1])) { 321 /* Simple red violation: color flip */ 322 RED(q) = 1; 323 RED(q->link[0]) = 0; 324 RED(q->link[1]) = 0; 325 } 326 327 if (is_red(q) && is_red(p)) { 328 /* Hard red violation: rotations necessary */ 329 int dir2 = (t->link[1] == g); 330 331 if (q == p->link[last]) 332 t->link[dir2] = rb_single(g, !last); 333 else 334 t->link[dir2] = rb_double(g, !last); 335 } 336 337 /* Stop working if we inserted a new node. */ 338 if (new_node) 339 break; 340 341 cmp_res = ct_compare(KEY(q), key); 342 if (cmp_res == 0) { /* key exists? */ 343 Py_XDECREF(VALUE(q)); /* release old value object */ 344 VALUE(q) = value; /* set new value object */ 345 Py_INCREF(value); /* take new value object */ 346 return 0; 347 } 348 last = dir; 349 dir = (cmp_res < 0); 350 351 /* Move the helpers down */ 352 if (g != NULL) 353 t = g; 354 355 g = p; 356 p = q; 357 q = q->link[dir]; 358 } 359 /* Update the root (it may be different) */ 360 root = head.link[1]; 361 } 362 363 /* Make the root black for simplified logic */ 364 RED(root) = 0; 365 (*rootaddr) = root; 366 return 1; 367 } 368 369 extern int 370 rb_remove(node_t **rootaddr, PyObject *key) 371 { 372 node_t *root = *rootaddr; 373 374 node_t head = { { NULL } }; /* False tree root */ 375 node_t *q, *p, *g; /* Helpers */ 376 node_t *f = NULL; /* Found item */ 377 int dir = 1; 378 379 if (root == NULL) 380 return 0; 381 382 /* Set up our helpers */ 383 q = &head; 384 g = p = NULL; 385 RIGHT_NODE(q) = root; 386 387 /* 388 Search and push a red node down 389 to fix red violations as we go 390 */ 391 while (q->link[dir] != NULL) { 392 int last = dir; 393 int cmp_res; 394 395 /* Move the helpers down */ 396 g = p, p = q; 397 q = q->link[dir]; 398 399 cmp_res = ct_compare(KEY(q), key); 400 401 dir = cmp_res < 0; 402 403 /* 404 Save the node with matching data and keep 405 going; we'll do removal tasks at the end 406 */ 407 if (cmp_res == 0) 408 f = q; 409 410 /* Push the red node down with rotations and color flips */ 411 if (!is_red(q) && !is_red(q->link[dir])) { 412 if (is_red(q->link[!dir])) 413 p = p->link[last] = rb_single(q, dir); 414 else if (!is_red(q->link[!dir])) { 415 node_t *s = p->link[!last]; 416 417 if (s != NULL) { 418 if (!is_red(s->link[!last]) && 419 !is_red(s->link[last])) { 420 /* Color flip */ 421 RED(p) = 0; 422 RED(s) = 1; 423 RED(q) = 1; 424 } 425 else { 426 int dir2 = g->link[1] == p; 427 428 if (is_red(s->link[last])) 429 g->link[dir2] = rb_double(p, last); 430 else if (is_red(s->link[!last])) 431 g->link[dir2] = rb_single(p, last); 432 433 /* Ensure correct coloring */ 434 RED(q) = RED(g->link[dir2]) = 1; 435 RED(g->link[dir2]->link[0]) = 0; 436 RED(g->link[dir2]->link[1]) = 0; 437 } 438 } 439 } 440 } 441 } 442 443 /* Replace and remove the saved node */ 444 if (f != NULL) { 445 ct_swap_data(f, q); 446 p->link[p->link[1] == q] = q->link[q->link[0] == NULL]; 447 ct_delete_node(q); 448 } 449 450 /* Update the root (it may be different) */ 451 root = head.link[1]; 452 453 /* Make the root black for simplified logic */ 454 if (root != NULL) 455 RED(root) = 0; 456 *rootaddr = root; 457 return (f != NULL); 458 } 459 460 #define avl_new_node(key, value) ct_new_node(key, value, 0) 461 #define height(p) ((p) == NULL ? -1 : (p)->xdata) 462 #define avl_max(a, b) ((a) > (b) ? (a) : (b)) 463 464 static node_t * 465 avl_single(node_t *root, int dir) 466 { 467 node_t *save = root->link[!dir]; 468 int rlh, rrh, slh; 469 470 /* Rotate */ 471 root->link[!dir] = save->link[dir]; 472 save->link[dir] = root; 473 474 /* Update balance factors */ 475 rlh = height(root->link[0]); 476 rrh = height(root->link[1]); 477 slh = height(save->link[!dir]); 478 479 BALANCE(root) = avl_max(rlh, rrh) + 1; 480 BALANCE(save) = avl_max(slh, BALANCE(root)) + 1; 481 482 return save; 483 } 484 485 static node_t * 486 avl_double(node_t *root, int dir) 487 { 488 root->link[!dir] = avl_single(root->link[!dir], !dir); 489 return avl_single(root, dir); 490 } 491 492 extern int 493 avl_insert(node_t **rootaddr, PyObject *key, PyObject *value) 494 { 495 node_t *root = *rootaddr; 496 497 if (root == NULL) { 498 root = avl_new_node(key, value); 499 if (root == NULL) 500 return -1; // got no memory 501 } 502 else { 503 node_t *it, *up[32]; 504 int upd[32], top = 0; 505 int done = 0; 506 int cmp_res; 507 508 it = root; 509 /* Search for an empty link, save the path */ 510 for (;;) { 511 /* Push direction and node onto stack */ 512 cmp_res = ct_compare(KEY(it), key); 513 if (cmp_res == 0) { 514 Py_XDECREF(VALUE(it)); // release old value object 515 VALUE(it) = value; // set new value object 516 Py_INCREF(value); // take new value object 517 return 0; 518 } 519 // upd[top] = it->data < data; 520 upd[top] = (cmp_res < 0); 521 up[top++] = it; 522 523 if (it->link[upd[top - 1]] == NULL) 524 break; 525 it = it->link[upd[top - 1]]; 526 } 527 528 /* Insert a new node at the bottom of the tree */ 529 it->link[upd[top - 1]] = avl_new_node(key, value); 530 if (it->link[upd[top - 1]] == NULL) 531 return -1; // got no memory 532 533 /* Walk back up the search path */ 534 while (--top >= 0 && !done) { 535 // int dir = (cmp_res < 0); 536 int lh, rh, max; 537 538 cmp_res = ct_compare(KEY(up[top]), key); 539 540 lh = height(up[top]->link[upd[top]]); 541 rh = height(up[top]->link[!upd[top]]); 542 543 /* Terminate or rebalance as necessary */ 544 if (lh - rh == 0) 545 done = 1; 546 if (lh - rh >= 2) { 547 node_t *a = up[top]->link[upd[top]]->link[upd[top]]; 548 node_t *b = up[top]->link[upd[top]]->link[!upd[top]]; 549 550 if (height( a ) >= height( b )) 551 up[top] = avl_single(up[top], !upd[top]); 552 else 553 up[top] = avl_double(up[top], !upd[top]); 554 555 /* Fix parent */ 556 if (top != 0) 557 up[top - 1]->link[upd[top - 1]] = up[top]; 558 else 559 root = up[0]; 560 done = 1; 561 } 562 /* Update balance factors */ 563 lh = height(up[top]->link[upd[top]]); 564 rh = height(up[top]->link[!upd[top]]); 565 max = avl_max(lh, rh); 566 BALANCE(up[top]) = max + 1; 567 } 568 } 569 (*rootaddr) = root; 570 return 1; 571 } 572 573 extern int 574 avl_remove(node_t **rootaddr, PyObject *key) 575 { 576 node_t *root = *rootaddr; 577 int cmp_res; 578 579 if (root != NULL) { 580 node_t *it, *up[32]; 581 int upd[32], top = 0; 582 583 it = root; 584 for (;;) { 585 /* Terminate if not found */ 586 if (it == NULL) 587 return 0; 588 cmp_res = ct_compare(KEY(it), key); 589 if (cmp_res == 0) 590 break; 591 592 /* Push direction and node onto stack */ 593 upd[top] = (cmp_res < 0); 594 up[top++] = it; 595 it = it->link[upd[top - 1]]; 596 } 597 598 /* Remove the node */ 599 if (it->link[0] == NULL || 600 it->link[1] == NULL) { 601 /* Which child is not null? */ 602 int dir = it->link[0] == NULL; 603 604 /* Fix parent */ 605 if (top != 0) 606 up[top - 1]->link[upd[top - 1]] = it->link[dir]; 607 else 608 root = it->link[dir]; 609 610 ct_delete_node(it); 611 } 612 else { 613 /* Find the inorder successor */ 614 node_t *heir = it->link[1]; 615 616 /* Save the path */ 617 upd[top] = 1; 618 up[top++] = it; 619 620 while ( heir->link[0] != NULL ) { 621 upd[top] = 0; 622 up[top++] = heir; 623 heir = heir->link[0]; 624 } 625 /* Swap data */ 626 ct_swap_data(it, heir); 627 /* Unlink successor and fix parent */ 628 up[top - 1]->link[up[top - 1] == it] = heir->link[1]; 629 ct_delete_node(heir); 630 } 631 632 /* Walk back up the search path */ 633 while (--top >= 0) { 634 int lh = height(up[top]->link[upd[top]]); 635 int rh = height(up[top]->link[!upd[top]]); 636 int max = avl_max(lh, rh); 637 638 /* Update balance factors */ 639 BALANCE(up[top]) = max + 1; 640 641 /* Terminate or rebalance as necessary */ 642 if (lh - rh == -1) 643 break; 644 if (lh - rh <= -2) { 645 node_t *a = up[top]->link[!upd[top]]->link[upd[top]]; 646 node_t *b = up[top]->link[!upd[top]]->link[!upd[top]]; 647 648 if (height(a) <= height(b)) 649 up[top] = avl_single(up[top], upd[top]); 650 else 651 up[top] = avl_double(up[top], upd[top]); 652 653 /* Fix parent */ 654 if (top != 0) 655 up[top - 1]->link[upd[top - 1]] = up[top]; 656 else 657 root = up[0]; 658 } 659 } 660 } 661 (*rootaddr) = root; 662 return 1; 663 } 664 665 extern node_t * 666 ct_succ_node(node_t *root, PyObject *key) 667 { 668 node_t *succ = NULL; 669 node_t *node = root; 670 int cval; 671 672 while (node != NULL) { 673 cval = ct_compare(key, KEY(node)); 674 if (cval == 0) 675 break; 676 else if (cval < 0) { 677 if ((succ == NULL) || 678 (ct_compare(KEY(node), KEY(succ)) < 0)) 679 succ = node; 680 node = LEFT_NODE(node); 681 } else 682 node = RIGHT_NODE(node); 683 } 684 if (node == NULL) 685 return NULL; 686 /* found node of key */ 687 if (RIGHT_NODE(node) != NULL) { 688 /* find smallest node of right subtree */ 689 node = RIGHT_NODE(node); 690 while (LEFT_NODE(node) != NULL) 691 node = LEFT_NODE(node); 692 if (succ == NULL) 693 succ = node; 694 else if (ct_compare(KEY(node), KEY(succ)) < 0) 695 succ = node; 696 } 697 return succ; 698 } 699 700 extern node_t * 701 ct_prev_node(node_t *root, PyObject *key) 702 { 703 node_t *prev = NULL; 704 node_t *node = root; 705 int cval; 706 707 while (node != NULL) { 708 cval = ct_compare(key, KEY(node)); 709 if (cval == 0) 710 break; 711 else if (cval < 0) 712 node = LEFT_NODE(node); 713 else { 714 if ((prev == NULL) || (ct_compare(KEY(node), KEY(prev)) > 0)) 715 prev = node; 716 node = RIGHT_NODE(node); 717 } 718 } 719 if (node == NULL) /* stay at dead end (None) */ 720 return NULL; 721 /* found node of key */ 722 if (LEFT_NODE(node) != NULL) { 723 /* find biggest node of left subtree */ 724 node = LEFT_NODE(node); 725 while (RIGHT_NODE(node) != NULL) 726 node = RIGHT_NODE(node); 727 if (prev == NULL) 728 prev = node; 729 else if (ct_compare(KEY(node), KEY(prev)) > 0) 730 prev = node; 731 } 732 return prev; 733 } 734 735 extern node_t * 736 ct_floor_node(node_t *root, PyObject *key) 737 { 738 node_t *prev = NULL; 739 node_t *node = root; 740 int cval; 741 742 while (node != NULL) { 743 cval = ct_compare(key, KEY(node)); 744 if (cval == 0) 745 return node; 746 else if (cval < 0) 747 node = LEFT_NODE(node); 748 else { 749 if ((prev == NULL) || (ct_compare(KEY(node), KEY(prev)) > 0)) 750 prev = node; 751 node = RIGHT_NODE(node); 752 } 753 } 754 return prev; 755 } 756 757 extern node_t * 758 ct_ceiling_node(node_t *root, PyObject *key) 759 { 760 node_t *succ = NULL; 761 node_t *node = root; 762 int cval; 763 764 while (node != NULL) { 765 cval = ct_compare(key, KEY(node)); 766 if (cval == 0) 767 return node; 768 else if (cval < 0) { 769 if ((succ == NULL) || 770 (ct_compare(KEY(node), KEY(succ)) < 0)) 771 succ = node; 772 node = LEFT_NODE(node); 773 } else 774 node = RIGHT_NODE(node); 775 } 776 return succ; 777 } 778 779 extern int 780 ct_index_of(node_t *root, PyObject *key) 781 /* 782 get index of item <key>, returns -1 if key not found. 783 */ 784 { 785 node_t *node = root; 786 int index = 0; 787 int go_down = 1; 788 node_stack_t *stack; 789 stack = stack_init(32); 790 791 for (;;) { 792 if ((LEFT_NODE(node) != NULL) && go_down) { 793 stack_push(stack, node); 794 node = LEFT_NODE(node); 795 } 796 else { 797 if (ct_compare(KEY(node), key) == 0) { 798 stack_delete(stack); 799 return index; 800 } 801 index++; 802 if (RIGHT_NODE(node) != NULL) { 803 node = RIGHT_NODE(node); 804 go_down = 1; 805 } 806 else { 807 if (stack_is_empty(stack)) { 808 stack_delete(stack); 809 return -1; 810 } 811 node = stack_pop(stack); 812 go_down = 0; 813 } 814 } 815 } 816 } 817 818 extern node_t * 819 ct_node_at(node_t *root, int index) 820 { 821 /* 822 root -- root node of tree 823 index -- index of wanted node 824 825 return NULL if index out of range 826 */ 827 node_t *node = root; 828 int counter = 0; 829 int go_down = 1; 830 node_stack_t *stack; 831 832 if (index < 0) return NULL; 833 834 stack = stack_init(32); 835 836 for(;;) { 837 if ((LEFT_NODE(node) != NULL) && go_down) { 838 stack_push(stack, node); 839 node = LEFT_NODE(node); 840 } 841 else { 842 if (counter == index) { 843 /* reached wanted index */ 844 stack_delete(stack); 845 return node; 846 } 847 counter++; 848 if (RIGHT_NODE(node) != NULL) { 849 node = RIGHT_NODE(node); 850 go_down = 1; 851 } 852 else { 853 if (stack_is_empty(stack)) { /* index out of range */ 854 stack_delete(stack); 855 return NULL; 856 } 857 node = stack_pop(stack); 858 go_down = 0; 859 } 860 } 861 } 862 } 863