Changeset cc27ae48 in mainline
- Timestamp:
- 2006-03-26T19:06:53Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 50fe620
- Parents:
- a2c4445
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/adt/btree.c
ra2c4445 rcc27ae48 34 34 * - technically, it is a B+-tree (because of the previous properties) 35 35 * 36 * Some of the functions below take pointer to the right-hand37 * side subtree pointer as parameter. Note that this is sufficient38 * because:39 * - New root node is passed the left-hand side subtree pointer40 * directly.41 * - node_split() always creates the right sibling and preserves42 * the original node (which becomes the left sibling).43 * There is always pointer to the left-hand side subtree44 * (i.e. left sibling) in the parent node.45 *46 36 * Be carefull when using these trees. They need to allocate 47 37 * and deallocate memory for their index nodes and as such … … 59 49 static void _btree_insert(btree_t *t, __native key, void *value, btree_node_t *rsubtree, btree_node_t *node); 60 50 static void node_initialize(btree_node_t *node); 61 static void node_insert_key (btree_node_t *node, __native key, void *value, btree_node_t *rsubtree);62 void node_remove_key(btree_node_t *node, __native key);51 static void node_insert_key_left(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); 52 static void node_insert_key_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); 63 53 static btree_node_t *node_split(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree, __native *median); 54 static void node_remove_key_left(btree_node_t *node, __native key); 55 static void node_remove_key_right(btree_node_t *node, __native key); 56 static index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right); 57 static bool try_insert_by_left_rotation(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); 58 static bool try_insert_by_right_rotation(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree); 64 59 65 60 #define ROOT_NODE(n) (!(n)->parent) … … 128 123 * Node conatins enough space, the key can be stored immediately. 129 124 */ 130 node_insert_key(node, key, value, rsubtree); 125 node_insert_key_right(node, key, value, rsubtree); 126 } else if (try_insert_by_left_rotation(node, key, value, rsubtree)) { 127 /* 128 * The key-value-rsubtree triplet has been inserted because 129 * some keys could have been moved to the left sibling. 130 */ 131 } else if (try_insert_by_right_rotation(node, key, value, rsubtree)) { 132 /* 133 * The key-value-rsubtree triplet has been inserted because 134 * some keys could have been moved to the right sibling. 135 */ 131 136 } else { 132 137 btree_node_t *rnode; … … 134 139 135 140 /* 136 * Node is full .137 * Split itand insert the smallest key from the node containing138 * bigger keys (i.e. the originalnode) into its parent.141 * Node is full and both siblings (if both exist) are full too. 142 * Split the node and insert the smallest key from the node containing 143 * bigger keys (i.e. the new node) into its parent. 139 144 */ 140 145 … … 149 154 * We split the root node. Create new root. 150 155 */ 151 152 156 t->root = (btree_node_t *) malloc(sizeof(btree_node_t), 0); 153 157 node->parent = t->root; … … 295 299 } 296 300 297 /** Insert key-value-right-subtree triplet into B-tree non-full node. 301 /** Insert key-value-lsubtree triplet into B-tree node. 302 * 303 * It is actually possible to have more keys than BTREE_MAX_KEYS. 304 * This feature is used during insert by right rotation. 305 * 306 * @param node B-tree node into wich the new key is to be inserted. 307 * @param key The key to be inserted. 308 * @param value Pointer to value to be inserted. 309 * @param lsubtree Pointer to the left subtree. 310 */ 311 void node_insert_key_left(btree_node_t *node, __native key, void *value, btree_node_t *lsubtree) 312 { 313 int i; 314 315 for (i = 0; i < node->keys; i++) { 316 if (key < node->key[i]) { 317 int j; 318 319 for (j = node->keys; j > i; j--) { 320 node->key[j] = node->key[j - 1]; 321 node->value[j] = node->value[j - 1]; 322 node->subtree[j + 1] = node->subtree[j]; 323 } 324 node->subtree[j + 1] = node->subtree[j]; 325 break; 326 } 327 } 328 node->key[i] = key; 329 node->value[i] = value; 330 node->subtree[i] = lsubtree; 331 332 node->keys++; 333 } 334 335 336 /** Insert key-value-rsubtree triplet into B-tree node. 298 337 * 299 338 * It is actually possible to have more keys than BTREE_MAX_KEYS. 300 339 * This feature is used during splitting the node when the 301 * number of keys is BTREE_MAX_KEYS + 1. 340 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation 341 * also makes use of this feature. 302 342 * 303 343 * @param node B-tree node into wich the new key is to be inserted. … … 306 346 * @param rsubtree Pointer to the right subtree. 307 347 */ 308 void node_insert_key (btree_node_t *node, __native key, void *value, btree_node_t *rsubtree)348 void node_insert_key_right(btree_node_t *node, __native key, void *value, btree_node_t *rsubtree) 309 349 { 310 350 int i; … … 322 362 } 323 363 } 324 325 364 node->key[i] = key; 326 365 node->value[i] = value; … … 356 395 ASSERT(median); 357 396 ASSERT(node->keys == BTREE_MAX_KEYS); 358 397 359 398 /* 360 399 * Use the extra space to store the extra node. 361 400 */ 362 node_insert_key (node, key, value, rsubtree);401 node_insert_key_right(node, key, value, rsubtree); 363 402 364 403 /* … … 402 441 } 403 442 404 /** Remove key from B-tree node. 443 /** Remove key and its left subtree pointer from B-tree node. 444 * 445 * Remove the key and eliminate gaps in node->key array. 446 * Note that the value pointer and the left subtree pointer 447 * is removed from the node as well. 405 448 * 406 449 * @param node B-tree node. 407 450 * @param key Key to be removed. 408 451 */ 409 void node_remove_key(btree_node_t *node, __native key) 410 { 452 void node_remove_key_left(btree_node_t *node, __native key) 453 { 454 int i, j; 455 456 for (i = 0; i < node->keys; i++) { 457 if (key == node->key[i]) { 458 for (j = i + 1; j < node->keys; j++) { 459 node->key[j - 1] = node->key[j]; 460 node->value[j - 1] = node->value[j]; 461 node->subtree[j - 1] = node->subtree[j]; 462 } 463 node->subtree[j - 1] = node->subtree[j]; 464 node->keys--; 465 return; 466 } 467 } 468 panic("node %P does not contain key %d\n", node, key); 469 } 470 471 /** Remove key and its right subtree pointer from B-tree node. 472 * 473 * Remove the key and eliminate gaps in node->key array. 474 * Note that the value pointer and the right subtree pointer 475 * is removed from the node as well. 476 * 477 * @param node B-tree node. 478 * @param key Key to be removed. 479 */ 480 void node_remove_key_right(btree_node_t *node, __native key) 481 { 482 int i, j; 483 484 for (i = 0; i < node->keys; i++) { 485 if (key == node->key[i]) { 486 for (j = i + 1; j < node->keys; j++) { 487 node->key[j - 1] = node->key[j]; 488 node->value[j - 1] = node->value[j]; 489 node->subtree[j] = node->subtree[j + 1]; 490 } 491 node->keys--; 492 return; 493 } 494 } 495 panic("node %P does not contain key %d\n", node, key); 496 } 497 498 /** Find key by its left or right subtree. 499 * 500 * @param node B-tree node. 501 * @param subtree Left or right subtree of a key found in node. 502 * @param right If true, subtree is a right subtree. If false, subtree is a left subtree. 503 * 504 * @return Index of the key associated with the subtree. 505 */ 506 index_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right) 507 { 508 int i; 509 510 for (i = 0; i < node->keys + 1; i++) { 511 if (subtree == node->subtree[i]) 512 return i - (int) (right != false); 513 } 514 panic("node %P does not contain subtree %P\n", node, subtree); 515 } 516 517 /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done. 518 * 519 * Left sibling of the node (if it exists) is checked for free space. 520 * If there is free space, the key is inserted and the smallest key of 521 * the node is moved there. The index node which is the parent of both 522 * nodes is fixed. 523 * 524 * @param node B-tree node. 525 * @param inskey Key to be inserted. 526 * @param insvalue Value to be inserted. 527 * @param rsubtree Right subtree of inskey. 528 * 529 * @return True if the rotation was performed, false otherwise. 530 */ 531 bool try_insert_by_left_rotation(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree) 532 { 533 index_t idx; 534 btree_node_t *lnode; 535 536 /* 537 * If this is root node, the rotation can not be done. 538 */ 539 if (ROOT_NODE(node)) 540 return false; 541 542 idx = find_key_by_subtree(node->parent, node, true); 543 if ((int) idx == -1) { 544 /* 545 * If this node is the leftmost subtree of its parent, 546 * the rotation can not be done. 547 */ 548 return false; 549 } 550 551 lnode = node->parent->subtree[idx]; 552 553 if (lnode->keys < BTREE_MAX_KEYS) { 554 __native key; 555 556 /* 557 * The rotaion can be done. The left sibling has free space. 558 */ 559 560 node_insert_key_right(node, inskey, insvalue, rsubtree); 561 key = node->key[0]; 562 563 if (LEAF_NODE(node)) { 564 void *value; 565 566 value = node->value[0]; 567 node_remove_key_left(node, key); 568 node_insert_key_right(lnode, key, value, NULL); 569 node->parent->key[idx] = node->key[0]; 570 } else { 571 btree_node_t *lsubtree; 572 573 lsubtree = node->subtree[0]; 574 node_remove_key_left(node, key); 575 node_insert_key_right(lnode, node->parent->key[idx], NULL, lsubtree); 576 node->parent->key[idx] = key; 577 578 /* Fix parent link of the reconnected left subtree. */ 579 lsubtree->parent = lnode; 580 } 581 return true; 582 } 583 584 return false; 585 } 586 587 /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done. 588 * 589 * Right sibling of the node (if it exists) is checked for free space. 590 * If there is free space, the key is inserted and the biggest key of 591 * the node is moved there. The index node which is the parent of both 592 * nodes is fixed. 593 * 594 * @param node B-tree node. 595 * @param inskey Key to be inserted. 596 * @param insvalue Value to be inserted. 597 * @param rsubtree Right subtree of inskey. 598 * 599 * @return True if the rotation was performed, false otherwise. 600 */ 601 bool try_insert_by_right_rotation(btree_node_t *node, __native inskey, void *insvalue, btree_node_t *rsubtree) 602 { 603 index_t idx; 604 btree_node_t *rnode; 605 606 /* 607 * If this is root node, the rotation can not be done. 608 */ 609 if (ROOT_NODE(node)) 610 return false; 611 612 idx = find_key_by_subtree(node->parent, node, false); 613 if (idx == node->parent->keys) { 614 /* 615 * If this node is the rightmost subtree of its parent, 616 * the rotation can not be done. 617 */ 618 return false; 619 } 620 621 rnode = node->parent->subtree[idx + 1]; 622 623 if (rnode->keys < BTREE_MAX_KEYS) { 624 __native key; 625 626 /* 627 * The rotaion can be done. The right sibling has free space. 628 */ 629 630 node_insert_key_right(node, inskey, insvalue, rsubtree); 631 key = node->key[node->keys - 1]; 632 633 if (LEAF_NODE(node)) { 634 void *value; 635 636 value = node->value[node->keys - 1]; 637 node_remove_key_right(node, key); 638 node_insert_key_left(rnode, key, value, NULL); 639 node->parent->key[idx] = key; 640 } else { 641 btree_node_t *rsubt; 642 643 rsubt = node->subtree[node->keys]; 644 node_remove_key_right(node, key); 645 node_insert_key_left(rnode, node->parent->key[idx], NULL, rsubt); 646 node->parent->key[idx] = key; 647 648 /* Fix parent link of the reconnected right subtree. */ 649 rsubt->parent = rnode; 650 } 651 return true; 652 } 653 654 return false; 411 655 } 412 656
Note:
See TracChangeset
for help on using the changeset viewer.