💾 Archived View for gmi.noulin.net › gitRepositories › wavlTree › file › wavlTree.c.gmi captured on 2023-07-10 at 15:54:29. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
wavlTree.c (15382B)
1 2 #include "wavlTree.h" 3 4 #define w (*tree) 5 #define n (*node) 6 #define p (*P) 7 #define o (*O) 8 #define x (*X) 9 10 /* enable/disable logging */ 11 #undef pLog 12 #define pLog(...) 13 14 #define freeP(ptr) do{\ 15 logI("free(%p);", ptr);\ 16 free(ptr);\ 17 }while(0) 18 19 20 static int height(t *tree); 21 static int nodeHeight(nodet *node); 22 static nodet *getEntry(t *tree, keyt key); 23 static valuet put(t *tree, keyt k, valuet v); 24 static void inOrderTraversal(nodet *X); 25 static void balanceAfterInsert(t *tree, nodet *X); 26 static bool needToRotateLeft(nodet *P); 27 static bool needToRotateRight(nodet *P); 28 static void rotateLeft(t *tree, nodet *P); 29 static void rotateRight(t *tree, nodet *P); 30 static valuet removeKV(t *tree, keyt k); 31 32 static void deleteEntry(t *tree, nodet *P); 33 static nodet *predecessor(nodet *X); 34 static void balanceAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank); 35 static void balanceAfterDeleteAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank); 36 37 static nodet *nodeNew(keyt k, valuet v, nodet *parent) { 38 nodet *r = malloc(sizeof(nodet)); 39 if (!r) return NULL; 40 r->key = k; 41 r->value = v; 42 r->left = NULL; 43 r->right = NULL; 44 r->parent = parent; 45 r->rank = 0; 46 return r; 47 } 48 49 int height(t *tree) { 50 return nodeHeight(w.root) - 1; 51 } 52 53 int nodeHeight(nodet *node) { 54 if (!node) { 55 return 0; 56 } 57 return (1 + maxV(nodeHeight(n.left), nodeHeight(n.right))); 58 } 59 60 /** 61 * return the value associated with key k 62 */ 63 static valuet get(t *tree, keyt k) { 64 nodet *X = getEntry(tree, k); 65 return !X ? -1 : x.value; 66 } 67 68 /** 69 * return map entry for the given key 70 */ 71 static nodet *getEntry(t *tree, keyt key) { 72 nodet *P = w.root; 73 while (P) { 74 int cmp = CMP(key, p.key); 75 if (cmp < 0) 76 P = p.left; 77 else if (cmp > 0) 78 P = p.right; 79 else { 80 logI("Entry: %p", P); 81 return P; 82 } 83 } 84 return NULL; 85 } 86 87 /** 88 * associate value v with key k 89 * 90 * \return 91 * previous value for key k 92 * -1 when k is not already in the tree 93 */ 94 static valuet put(t *tree, keyt k, valuet v) { 95 nodet *O = w.root; 96 if (!O) { 97 // tree is empty, new node is root 98 w.root = nodeNew(k, v, NULL); 99 w.count = 1; 100 w.modCount++; 101 //return NULL; 102 return -1; 103 } 104 105 // Find the proper position for this new node 106 int cmp; 107 nodet *P; 108 do { 109 P = O; 110 cmp = CMP(k, o.key); 111 // Decide which side of the current parent-under-consideration the 112 // new node to be inserted belongs on. 113 if (cmp < 0) 114 O = o.left; 115 else if (cmp > 0) 116 O = o.right; 117 else { 118 // Looks like we collided with an object in the tree which has 119 // the same key as the key in parameters 120 // return previous value 121 valuet r = o.value; 122 o.value = v; 123 return r; 124 } 125 // If we would have run out of valid pointers in the direction we 126 // should be searching, then we are done 127 } while(O); 128 129 nodet *e = nodeNew(k, v, P); 130 logI("New %p", e); 131 if (cmp < 0) { 132 p.left = e; 133 } 134 else { 135 p.right = e; 136 } 137 138 if (!p.rank) { 139 p.rank++; 140 balanceAfterInsert(tree, P); 141 } 142 143 w.count++; 144 w.modCount++; 145 146 //return NULL; 147 return -1; 148 } 149 150 static void inOrderTraversal(nodet *X) { 151 if (!X) return; 152 153 /* printf("value %d, rank %d", x.value, x.rank); */ 154 /* if (x.left) { */ 155 /* printf(" left key %d", x.left->key); */ 156 /* } */ 157 /* else */ 158 /* printf(" no left"); */ 159 /* if (x.right) { */ 160 /* printf(" right key %d", x.right->key); */ 161 /* } */ 162 /* else */ 163 /* printf(" no right"); */ 164 /* printf("\n"); */ 165 166 inOrderTraversal(x.left); 167 printf("value %d, rank %d\n", x.value, x.rank); 168 inOrderTraversal(x.right); 169 } 170 171 /** 172 * - If the path of incremented ranks reaches the root of the tree stop. 173 * - If the path of incremented ranks reaches a node whose parent's rank previously differed by two and after incrementing now differ by one stop. 174 * - If the procedure increases the rank of a node x, so that it becomes equal to the rank of the parent y of x, 175 * but the other child of y has a rank that is smaller by two (so that the rank of y cannot be increased) 176 * then again the rebalancing procedure stops after performing rotations necessary. 177 * 178 * In other words: 179 * After insertion rank difference is 1,2 or 3 - 180 * check these three cases stopping after any rotations, reaching the root or when rank difference was 2 before the insertion. 181 */ 182 static void balanceAfterInsert(t *tree, nodet *X) { 183 for(nodet *P = x.parent ; P && (x.rank+1 != p.rank) ; x.rank++) { 184 if (p.left == X) { 185 // new node was added on the left 186 if (needToRotateRight(P)) { 187 if (!x.left || x.rank >= x.left->rank+2) { 188 x.rank--; 189 x.right->rank++; 190 rotateLeft(tree, X); 191 } 192 p.rank--; 193 rotateRight(tree, P); 194 break; 195 } 196 } 197 else { 198 if (needToRotateLeft(P)) { 199 if (!x.right || x.rank >= x.right->rank+2) { 200 x.rank--; 201 x.left->rank++; 202 rotateRight(tree, X); 203 } 204 p.rank--; 205 rotateLeft(tree, P); 206 break; 207 } 208 } 209 X = P; 210 P = x.parent; 211 } 212 } 213 214 static bool needToRotateLeft(nodet *P) { 215 if (!p.left) { 216 // rank of sibling is -1 217 if (p.rank == 1) 218 return true; 219 return false; 220 } 221 else if (p.rank >= p.left->rank + 2) 222 return true; 223 return false; 224 } 225 226 static bool needToRotateRight(nodet *P) { 227 if (!p.right) { 228 // rank of sibling is -1 229 if (p.rank == 1) 230 return true; 231 return false; 232 } 233 else if (p.rank >= p.right->rank + 2) 234 return true; 235 return false; 236 } 237 238 static void rotateLeft(t *tree, nodet *P) { 239 nodet *X = p.right; 240 p.right = x.left; 241 if (x.left) 242 x.left->parent = P; 243 x.parent = p.parent; 244 if (!p.parent) 245 w.root = X; 246 else if (p.parent->left == P) 247 p.parent->left = X; 248 else 249 p.parent->right = X; 250 x.left = P; 251 p.parent = X; 252 w.rotations++; 253 } 254 255 static void rotateRight(t *tree, nodet *P) { 256 nodet *X = p.left; 257 p.left = x.right; 258 if (x.right) 259 x.right->parent = P; 260 x.parent = p.parent; 261 if (!p.parent) 262 w.root = X; 263 else if (p.parent->right == P) 264 p.parent->right = X; 265 else 266 p.parent->left = X; 267 x.right = P; 268 p.parent = X; 269 w.rotations++; 270 } 271 272 /** 273 * remove key and value if key is present in tree 274 * 275 * \return 276 * previous value for key k 277 * -1 when k was not in the tree 278 */ 279 valuet removeKV(t *tree, keyt k) { 280 nodet *P = getEntry(tree, k); 281 if (!P) 282 //return NULL; 283 return -1; 284 285 valuet oldValue = p.value; 286 deleteEntry(tree, P); 287 return oldValue; 288 } 289 290 /** 291 * delete node P and then rebalance the tree 292 */ 293 static void deleteEntry(t *tree, nodet *P) { 294 w.modCount++; 295 w.count--; 296 297 // If strictly internal, copy successor's element to p and then make p 298 // point to successor. 299 if (p.left && p.right) { 300 nodet *X = predecessor(P); 301 p.key = x.key; 302 p.value = x.value; 303 P = X; 304 } // p has 2 children 305 306 nodet *replacement = (p.left ? p.left : p.right); 307 if (replacement) { 308 // Link replacement to parent 309 replacement->parent = p.parent; 310 nodet *sibling = NULL; 311 if (!p.parent) { 312 w.root = replacement; 313 freeP(P); 314 return; 315 } 316 else if (P == p.parent->left) { 317 p.parent->left = replacement; 318 sibling = p.parent->right; 319 } else { 320 p.parent->right = replacement; 321 sibling = p.parent->left; 322 } 323 324 // Null out links so they are OK to use by fixAfterDeletion. 325 p.left = p.right = p.parent = NULL; 326 freeP(P); 327 if (w.deleteWAVL) 328 balanceAfterDeleteWAVL(tree, replacement->parent, sibling, replacement->rank); 329 else 330 balanceAfterDeleteAVL(tree, replacement->parent, sibling, replacement->rank); 331 } 332 else if (!p.parent) { 333 // return if we are the only node. 334 freeP(P); 335 w.root = NULL; 336 return; 337 } 338 else { 339 // No children. Use self as phantom replacement and unlink. 340 nodet *fixPoint = p.parent; 341 nodet *sibling = NULL; 342 343 if (P == p.parent->left) { 344 p.parent->left = NULL; 345 sibling = fixPoint->right; 346 } 347 else if (P == p.parent->right) { 348 p.parent->right = NULL; 349 sibling = fixPoint->left; 350 } 351 p.parent = NULL; 352 int8_t rk = --p.rank; 353 freeP(P); 354 if (w.deleteWAVL) 355 balanceAfterDeleteWAVL(tree, fixPoint, sibling, rk); 356 else 357 balanceAfterDeleteAVL(tree, fixPoint, sibling, rk); 358 } 359 } 360 361 static int8_t rank(nodet *node) { 362 return !node ? -1 : n.rank; 363 } 364 365 static bool nodeIsTwoTwo(nodet *node) { 366 if (!node || !n.rank) 367 return false; 368 if (n.rank == 1) { 369 if (!n.left && !n.right) 370 return true; 371 else 372 return false; 373 } 374 else 375 return (n.left->rank == n.right->rank && (n.left->rank + 2 == n.rank)); 376 } 377 378 static void balanceAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank) { 379 nodet *node; 380 int deltaRank = parent->rank - nodeRank; 381 while (deltaRank == 3 || parent->rank == 1 && nodeIsTwoTwo(parent)) { 382 int deltaRankSibling = (!sibling) ? parent->rank + 1 : parent->rank - sibling->rank; 383 if (deltaRankSibling == 2) { 384 parent->rank--; // demote and continue loop 385 } else { 386 int deltaRankSiblingL = sibling->rank - rank(sibling->left); 387 int deltaRankSiblingR = sibling->rank - rank(sibling->right); 388 389 if (deltaRankSiblingL == 2 && deltaRankSiblingR == 2) { 390 // "double demote" in the orig. paper since both parent & sibling demote 391 parent->rank--; 392 sibling->rank--; 393 } 394 else if (parent->right == sibling) { 395 // delete was on the left 396 if (deltaRankSiblingR == 1) { 397 // single rotation 398 sibling->rank++; 399 parent->rank--; 400 if (!sibling->left) 401 parent->rank--; // demote parent again 402 rotateLeft(tree, parent); 403 } 404 else { 405 // double rotation 406 parent->rank -= 2; 407 sibling->rank--; 408 sibling->left->rank += 2; 409 rotateRight(tree, sibling); 410 rotateLeft(tree, parent); 411 } 412 break; 413 } 414 else { 415 // delete was on the right 416 if (deltaRankSiblingL == 1) { 417 // single rotation 418 sibling->rank++; 419 parent->rank--; 420 if (!sibling->right) 421 parent->rank--; // demote parent again 422 rotateRight(tree, parent); 423 } 424 else { 425 // double rotation 426 parent->rank -= 2; 427 sibling->rank--; 428 sibling->right->rank += 2; 429 rotateLeft(tree, sibling); 430 rotateRight(tree, parent); 431 } 432 break; 433 } 434 } 435 436 if (!parent->parent) 437 return; 438 node = parent; 439 parent = parent->parent; 440 sibling = (parent->left == node) ? parent->right : parent->left; 441 deltaRank = parent->rank - n.rank; 442 } 443 } 444 445 static void balanceAfterDeleteAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank) { 446 nodet *node; 447 int balance; 448 if (!sibling) 449 // remove sibling null check inside loop by testing once here 450 balance = -1 - nodeRank; 451 else 452 balance = sibling->rank - nodeRank; 453 454 while (balance != 1) { 455 // balance == 1 means prior to delete parent was balanced, break; 456 if (balance == 0) { 457 // side of delete was taller, decrement and continue 458 parent->rank--; 459 } 460 else if (parent->left == sibling) { 461 parent->rank -= 2; 462 int siblingBalance = rank(sibling->right) - rank(sibling->left); 463 if (siblingBalance == 0) { 464 // parent height unchanged after rotate so break 465 sibling->rank++; 466 parent->rank++; 467 rotateRight(tree, parent); 468 break; 469 } 470 else if (siblingBalance > 0) { 471 sibling->right->rank++; 472 sibling->rank--; 473 rotateLeft(tree, sibling); 474 } 475 rotateRight(tree, parent); 476 parent = parent->parent; 477 } 478 else { 479 // delete on left 480 parent->rank -= 2; 481 int siblingBalance = rank(sibling->right) - rank(sibling->left); 482 if (siblingBalance == 0) { 483 // parent height unchanged after rotate so break 484 sibling->rank++; 485 parent->rank++; 486 rotateLeft(tree, parent); 487 break; 488 } 489 else if (siblingBalance < 0) { 490 sibling->left->rank++; 491 sibling->rank--; 492 rotateRight(tree, sibling); 493 } 494 rotateLeft(tree, parent); 495 parent = parent->parent; 496 } 497 498 if (!parent->parent) 499 return; 500 node = parent; 501 parent = parent->parent; 502 sibling = (parent->left == node) ? parent->right : parent->left; 503 balance = sibling->rank - n.rank; 504 } 505 } 506 507 static void freeNodes(nodet *X) { 508 if (!X) return; 509 freeNodes(x.left); 510 freeNodes(x.right); 511 freeP(X); 512 } 513 514 static void clear(t *tree) { 515 freeNodes(w.root); 516 w.modCount++; 517 w.count = 0; 518 w.root = NULL; 519 w.rotations = 0; 520 w.deleteWAVL = false; 521 } 522 523 static nodet *getFirstEntry(t *tree) { 524 nodet *P = w.root; 525 if (P) { 526 while (p.left) 527 P = p.left; 528 } 529 return P; 530 } 531 532 static nodet *getLastEntry(t *tree) { 533 nodet *P = w.root; 534 if (P) { 535 while (p.right) 536 P = p.right; 537 } 538 return P; 539 } 540 541 // TODO add leftMost, rightMost pointer in tree 542 543 static nodet *successor(nodet *X) { 544 if (!X) 545 return NULL; 546 else if (x.right != NULL) { 547 nodet *P = x.right; 548 while (p.left) 549 P = p.left; 550 return P; 551 } 552 else { 553 nodet *P = x.parent; 554 nodet *ch = X; 555 while (P && ch == p.right) { 556 ch = P; 557 P = p.parent; 558 } 559 return P; 560 } 561 } 562 563 static nodet *predecessor(nodet *X) { 564 if (!X) 565 return NULL; 566 else if (x.left) { 567 nodet *P = x.left; 568 while (p.right) 569 P = p.right; 570 return P; 571 } 572 else { 573 nodet *P = x.parent; 574 nodet *ch = X; 575 while (P && ch == p.left) { 576 ch = P; 577 P = p.parent; 578 } 579 return P; 580 } 581 } 582 583 static void iterStart(t *tree, nodet *first) { 584 w.expectedModCount = w.modCount; 585 w.lastReturned = NULL; 586 w.next = first; 587 } 588 589 static bool hasNext(t *tree) { 590 return w.next != NULL; 591 } 592 593 static nodet *nextEntry(t *tree) { 594 nodet *e = w.next; 595 if (!e) return NULL; 596 if (w.modCount != w.expectedModCount) return NULL; 597 w.next = successor(e); 598 w.lastReturned = e; 599 return e; 600 } 601 602 static nodet *prevEntry(t *tree) { 603 nodet *e = w.next; 604 if (!e) return NULL; 605 if (w.modCount != w.expectedModCount) return NULL; 606 w.next = predecessor(e); 607 w.lastReturned = e; 608 return e; 609 } 610 611 static bool removeCurrent(t *tree) { 612 if (!w.lastReturned) return false; 613 if (w.modCount != w.expectedModCount) return false; 614 /* // deleted entries are replaced by their successors */ 615 /* if (w.lastReturned.left && w.lastReturned.right) */ 616 /* w.next = w.lastReturned; */ 617 deleteEntry(tree, w.lastReturned); 618 w.expectedModCount = w.modCount; 619 w.lastReturned = NULL; 620 return true; 621 } 622 623 /** 624 * initialize tree data 625 */ 626 bool init(t *tree) { 627 if (!tree) return false; 628 629 w.count = 0; 630 w.modCount = 0; 631 w.rotations = 0; 632 w.deleteWAVL = false; 633 w.root = NULL; 634 635 w.get = get; 636 w.put = put; 637 w.treeHeight = height; 638 w.remove = removeKV; 639 w.inOrderTraversal = inOrderTraversal; 640 w.clear = clear; 641 w.getFirstEntry = getFirstEntry; 642 w.getLastEntry = getLastEntry; 643 w.iterStart = iterStart; 644 w.hasNext = hasNext; 645 w.nextEntry = nextEntry; 646 w.prevEntry = prevEntry; 647 w.removeCurrent = removeCurrent; 648 649 return true; 650 } 651 652 // vim: set expandtab ts=2 sw=2: