1.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 2.\" 3.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 3. All advertising materials mentioning features or use of this software 15.\" must display the following acknowledgement: 16.\" This product includes software developed by Niels Provos. 17.\" 4. The name of the author may not be used to endorse or promote products 18.\" derived from this software without specific prior written permission. 19.\" 20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30.\" 31.\" $FreeBSD$ 32.\" 33.Dd July 27, 2020 34.Dt TREE 3 35.Os 36.Sh NAME 37.Nm SPLAY_PROTOTYPE , 38.Nm SPLAY_GENERATE , 39.Nm SPLAY_ENTRY , 40.Nm SPLAY_HEAD , 41.Nm SPLAY_INITIALIZER , 42.Nm SPLAY_ROOT , 43.Nm SPLAY_EMPTY , 44.Nm SPLAY_NEXT , 45.Nm SPLAY_MIN , 46.Nm SPLAY_MAX , 47.Nm SPLAY_FIND , 48.Nm SPLAY_LEFT , 49.Nm SPLAY_RIGHT , 50.Nm SPLAY_FOREACH , 51.Nm SPLAY_INIT , 52.Nm SPLAY_INSERT , 53.Nm SPLAY_REMOVE , 54.Nm RB_PROTOTYPE , 55.Nm RB_PROTOTYPE_STATIC , 56.Nm RB_PROTOTYPE_INSERT , 57.Nm RB_PROTOTYPE_INSERT_COLOR , 58.Nm RB_PROTOTYPE_REMOVE , 59.Nm RB_PROTOTYPE_REMOVE_COLOR , 60.Nm RB_PROTOTYPE_FIND , 61.Nm RB_PROTOTYPE_NFIND , 62.Nm RB_PROTOTYPE_NEXT , 63.Nm RB_PROTOTYPE_PREV , 64.Nm RB_PROTOTYPE_MINMAX , 65.Nm RB_PROTOTYPE_REINSERT , 66.Nm RB_GENERATE , 67.Nm RB_GENERATE_STATIC , 68.Nm RB_GENERATE_INSERT , 69.Nm RB_GENERATE_INSERT_COLOR , 70.Nm RB_GENERATE_REMOVE , 71.Nm RB_GENERATE_REMOVE_COLOR , 72.Nm RB_GENERATE_FIND , 73.Nm RB_GENERATE_NFIND , 74.Nm RB_GENERATE_NEXT , 75.Nm RB_GENERATE_PREV , 76.Nm RB_GENERATE_MINMAX , 77.Nm RB_GENERATE_REINSERT , 78.Nm RB_ENTRY , 79.Nm RB_HEAD , 80.Nm RB_INITIALIZER , 81.Nm RB_ROOT , 82.Nm RB_EMPTY , 83.Nm RB_NEXT , 84.Nm RB_PREV , 85.Nm RB_MIN , 86.Nm RB_MAX , 87.Nm RB_FIND , 88.Nm RB_NFIND , 89.Nm RB_LEFT , 90.Nm RB_RIGHT , 91.Nm RB_PARENT , 92.Nm RB_FOREACH , 93.Nm RB_FOREACH_FROM , 94.Nm RB_FOREACH_SAFE , 95.Nm RB_FOREACH_REVERSE , 96.Nm RB_FOREACH_REVERSE_FROM , 97.Nm RB_FOREACH_REVERSE_SAFE , 98.Nm RB_INIT , 99.Nm RB_INSERT , 100.Nm RB_REMOVE , 101.Nm RB_REINSERT , 102.Nm RB_AUGMENT 103.Nm RB_AUGMENT_CHECK, 104.Nm RB_UPDATE_AUGMENT 105.Nd "implementations of splay and rank-balanced (wavl) trees" 106.Sh SYNOPSIS 107.In sys/tree.h 108.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP 109.Fn SPLAY_GENERATE NAME TYPE FIELD CMP 110.Fn SPLAY_ENTRY TYPE 111.Fn SPLAY_HEAD HEADNAME TYPE 112.Ft "struct TYPE *" 113.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 114.Fn SPLAY_ROOT "SPLAY_HEAD *head" 115.Ft bool 116.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 117.Ft "struct TYPE *" 118.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 119.Ft "struct TYPE *" 120.Fn SPLAY_MIN NAME "SPLAY_HEAD *head" 121.Ft "struct TYPE *" 122.Fn SPLAY_MAX NAME "SPLAY_HEAD *head" 123.Ft "struct TYPE *" 124.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm" 125.Ft "struct TYPE *" 126.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 127.Ft "struct TYPE *" 128.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 129.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head" 130.Ft void 131.Fn SPLAY_INIT "SPLAY_HEAD *head" 132.Ft "struct TYPE *" 133.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 134.Ft "struct TYPE *" 135.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm" 136.Fn RB_PROTOTYPE NAME TYPE FIELD CMP 137.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP 138.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR 139.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR 140.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR 141.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR 142.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR 143.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR 144.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR 145.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR 146.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR 147.Fn RB_PROTOTYPE_REINSERT NAME TYPE ATTR 148.Fn RB_GENERATE NAME TYPE FIELD CMP 149.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP 150.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR 151.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR 152.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR 153.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR 154.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR 155.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR 156.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR 157.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR 158.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR 159.Fn RB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR 160.Fn RB_ENTRY TYPE 161.Fn RB_HEAD HEADNAME TYPE 162.Fn RB_INITIALIZER "RB_HEAD *head" 163.Ft "struct TYPE *" 164.Fn RB_ROOT "RB_HEAD *head" 165.Ft "bool" 166.Fn RB_EMPTY "RB_HEAD *head" 167.Ft "struct TYPE *" 168.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" 169.Ft "struct TYPE *" 170.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm" 171.Ft "struct TYPE *" 172.Fn RB_MIN NAME "RB_HEAD *head" 173.Ft "struct TYPE *" 174.Fn RB_MAX NAME "RB_HEAD *head" 175.Ft "struct TYPE *" 176.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm" 177.Ft "struct TYPE *" 178.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm" 179.Ft "struct TYPE *" 180.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 181.Ft "struct TYPE *" 182.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 183.Ft "struct TYPE *" 184.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 185.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head" 186.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" 187.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 188.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head" 189.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" 190.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 191.Ft void 192.Fn RB_INIT "RB_HEAD *head" 193.Ft "struct TYPE *" 194.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm" 195.Ft "struct TYPE *" 196.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm" 197.Ft "struct TYPE *" 198.Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm" 199.Ft "void" 200.Fn RB_AUGMENT NAME "struct TYPE *elm" 201.Ft "bool" 202.Fn RB_AUGMENT_CHECK NAME "struct TYPE *elm" 203.Ft "void" 204.Fn RB_UPDATE_AUGMENT NAME "struct TYPE *elm" 205.Sh DESCRIPTION 206These macros define data structures for different types of trees: 207splay trees and rank-balanced (wavl) trees. 208.Pp 209In the macro definitions, 210.Fa TYPE 211is the name tag of a user defined structure that must contain a field of type 212.Vt SPLAY_ENTRY , 213or 214.Vt RB_ENTRY , 215named 216.Fa ENTRYNAME . 217The argument 218.Fa HEADNAME 219is the name tag of a user defined structure that must be declared 220using the macros 221.Fn SPLAY_HEAD , 222or 223.Fn RB_HEAD . 224The argument 225.Fa NAME 226has to be a unique name prefix for every tree that is defined. 227.Pp 228The function prototypes are declared with 229.Fn SPLAY_PROTOTYPE , 230.Fn RB_PROTOTYPE , 231or 232.Fn RB_PROTOTYPE_STATIC . 233The function bodies are generated with 234.Fn SPLAY_GENERATE , 235.Fn RB_GENERATE , 236or 237.Fn RB_GENERATE_STATIC . 238See the examples below for further explanation of how these macros are used. 239.Sh SPLAY TREES 240A splay tree is a self-organizing data structure. 241Every operation on the tree causes a splay to happen. 242The splay moves the requested 243node to the root of the tree and partly rebalances it. 244.Pp 245This has the benefit that request locality causes faster lookups as 246the requested nodes move to the top of the tree. 247On the other hand, every lookup causes memory writes. 248.Pp 249The Balance Theorem bounds the total access time for 250.Ar m 251operations and 252.Ar n 253inserts on an initially empty tree as 254.Fn O "\*[lp]m + n\*[rp]lg n" . 255The 256amortized cost for a sequence of 257.Ar m 258accesses to a splay tree is 259.Fn O "lg n" . 260.Pp 261A splay tree is headed by a structure defined by the 262.Fn SPLAY_HEAD 263macro. 264A 265structure is declared as follows: 266.Bd -ragged -offset indent 267.Fn SPLAY_HEAD HEADNAME TYPE 268.Va head ; 269.Ed 270.Pp 271where 272.Fa HEADNAME 273is the name of the structure to be defined, and struct 274.Fa TYPE 275is the type of the elements to be inserted into the tree. 276.Pp 277The 278.Fn SPLAY_ENTRY 279macro declares a structure that allows elements to be connected in the tree. 280.Pp 281In order to use the functions that manipulate the tree structure, 282their prototypes need to be declared with the 283.Fn SPLAY_PROTOTYPE 284macro, 285where 286.Fa NAME 287is a unique identifier for this particular tree. 288The 289.Fa TYPE 290argument is the type of the structure that is being managed 291by the tree. 292The 293.Fa FIELD 294argument is the name of the element defined by 295.Fn SPLAY_ENTRY . 296.Pp 297The function bodies are generated with the 298.Fn SPLAY_GENERATE 299macro. 300It takes the same arguments as the 301.Fn SPLAY_PROTOTYPE 302macro, but should be used only once. 303.Pp 304Finally, 305the 306.Fa CMP 307argument is the name of a function used to compare tree nodes 308with each other. 309The function takes two arguments of type 310.Vt "struct TYPE *" . 311If the first argument is smaller than the second, the function returns a 312value smaller than zero. 313If they are equal, the function returns zero. 314Otherwise, it should return a value greater than zero. 315The compare 316function defines the order of the tree elements. 317.Pp 318The 319.Fn SPLAY_INIT 320macro initializes the tree referenced by 321.Fa head . 322.Pp 323The splay tree can also be initialized statically by using the 324.Fn SPLAY_INITIALIZER 325macro like this: 326.Bd -ragged -offset indent 327.Fn SPLAY_HEAD HEADNAME TYPE 328.Va head 329= 330.Fn SPLAY_INITIALIZER &head ; 331.Ed 332.Pp 333The 334.Fn SPLAY_INSERT 335macro inserts the new element 336.Fa elm 337into the tree. 338.Pp 339The 340.Fn SPLAY_REMOVE 341macro removes the element 342.Fa elm 343from the tree pointed by 344.Fa head . 345.Pp 346The 347.Fn SPLAY_FIND 348macro can be used to find a particular element in the tree. 349.Bd -literal -offset indent 350struct TYPE find, *res; 351find.key = 30; 352res = SPLAY_FIND(NAME, head, &find); 353.Ed 354.Pp 355The 356.Fn SPLAY_ROOT , 357.Fn SPLAY_MIN , 358.Fn SPLAY_MAX , 359and 360.Fn SPLAY_NEXT 361macros can be used to traverse the tree: 362.Bd -literal -offset indent 363for (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 364.Ed 365.Pp 366Or, for simplicity, one can use the 367.Fn SPLAY_FOREACH 368macro: 369.Bd -ragged -offset indent 370.Fn SPLAY_FOREACH np NAME head 371.Ed 372.Pp 373The 374.Fn SPLAY_EMPTY 375macro should be used to check whether a splay tree is empty. 376.Sh RANK-BALANCED TREES 377Rank-balanced (RB) trees are a framework for defining height-balanced 378binary search trees, including AVL and red-black trees. 379Each tree node has an associated rank. 380Balance conditions are expressed by conditions on the differences in 381rank between any node and its children. 382Rank differences are stored in each tree node. 383.Pp 384The balance conditions implemented by the RB macros lead to weak AVL 385(wavl) trees, which combine the best aspects of AVL and red-black 386trees. 387Wavl trees rebalance after an insertion in the same way AVL trees do, 388with the same worst-case time as red-black trees offer, and with 389better balance in the resulting tree. 390Wavl trees rebalance after a removal in a way that requires less 391restructuring, in the worst case, than either AVL or red-black trees 392do. 393Removals can lead to a tree almost as unbalanced as a red-black 394tree; insertions lead to a tree becoming as balanced as an AVL tree. 395.Pp 396A rank-balanced tree is headed by a structure defined by the 397.Fn RB_HEAD 398macro. 399A 400structure is declared as follows: 401.Bd -ragged -offset indent 402.Fn RB_HEAD HEADNAME TYPE 403.Va head ; 404.Ed 405.Pp 406where 407.Fa HEADNAME 408is the name of the structure to be defined, and struct 409.Fa TYPE 410is the type of the elements to be inserted into the tree. 411.Pp 412The 413.Fn RB_ENTRY 414macro declares a structure that allows elements to be connected in the tree. 415.Pp 416In order to use the functions that manipulate the tree structure, 417their prototypes need to be declared with the 418.Fn RB_PROTOTYPE 419or 420.Fn RB_PROTOTYPE_STATIC 421macro, 422where 423.Fa NAME 424is a unique identifier for this particular tree. 425The 426.Fa TYPE 427argument is the type of the structure that is being managed 428by the tree. 429The 430.Fa FIELD 431argument is the name of the element defined by 432.Fn RB_ENTRY . 433Individual prototypes can be declared with 434.Fn RB_PROTOTYPE_INSERT , 435.Fn RB_PROTOTYPE_INSERT_COLOR , 436.Fn RB_PROTOTYPE_REMOVE , 437.Fn RB_PROTOTYPE_REMOVE_COLOR , 438.Fn RB_PROTOTYPE_FIND , 439.Fn RB_PROTOTYPE_NFIND , 440.Fn RB_PROTOTYPE_NEXT , 441.Fn RB_PROTOTYPE_PREV , 442.Fn RB_PROTOTYPE_MINMAX , 443and 444.Fn RB_PROTOTYPE_REINSERT 445in case not all functions are required. 446The individual prototype macros expect 447.Fa NAME , 448.Fa TYPE , 449and 450.Fa ATTR 451arguments. 452The 453.Fa ATTR 454argument must be empty for global functions or 455.Fa static 456for static functions. 457.Pp 458The function bodies are generated with the 459.Fn RB_GENERATE 460or 461.Fn RB_GENERATE_STATIC 462macro. 463These macros take the same arguments as the 464.Fn RB_PROTOTYPE 465and 466.Fn RB_PROTOTYPE_STATIC 467macros, but should be used only once. 468As an alternative individual function bodies are generated with the 469.Fn RB_GENERATE_INSERT , 470.Fn RB_GENERATE_INSERT_COLOR , 471.Fn RB_GENERATE_REMOVE , 472.Fn RB_GENERATE_REMOVE_COLOR , 473.Fn RB_GENERATE_FIND , 474.Fn RB_GENERATE_NFIND , 475.Fn RB_GENERATE_NEXT , 476.Fn RB_GENERATE_PREV , 477.Fn RB_GENERATE_MINMAX , 478and 479.Fn RB_GENERATE_REINSERT 480macros. 481.Pp 482Finally, 483the 484.Fa CMP 485argument is the name of a function used to compare tree nodes 486with each other. 487The function takes two arguments of type 488.Vt "struct TYPE *" . 489If the first argument is smaller than the second, the function returns a 490value smaller than zero. 491If they are equal, the function returns zero. 492Otherwise, it should return a value greater than zero. 493The compare 494function defines the order of the tree elements. 495.Pp 496The 497.Fn RB_INIT 498macro initializes the tree referenced by 499.Fa head . 500.Pp 501The rank-balanced tree can also be initialized statically by using the 502.Fn RB_INITIALIZER 503macro like this: 504.Bd -ragged -offset indent 505.Fn RB_HEAD HEADNAME TYPE 506.Va head 507= 508.Fn RB_INITIALIZER &head ; 509.Ed 510.Pp 511The 512.Fn RB_INSERT 513macro inserts the new element 514.Fa elm 515into the tree. 516.Pp 517The 518.Fn RB_REMOVE 519macro removes the element 520.Fa elm 521from the tree pointed by 522.Fa head . 523.Pp 524The 525.Fn RB_FIND 526and 527.Fn RB_NFIND 528macros can be used to find a particular element in the tree. 529.Pp 530The 531.Fn RB_FIND 532macro returns the element in the tree equal to the provided 533key, or 534.Dv NULL 535if there is no such element. 536.Pp 537The 538.Fn RB_NFIND 539macro returns the least element greater than or equal to the provided 540key, or 541.Dv NULL 542if there is no such element. 543.Bd -literal -offset indent 544struct TYPE find, *res, *resn; 545find.key = 30; 546res = RB_FIND(NAME, head, &find); 547resn = RB_NFIND(NAME, head, &find); 548.Ed 549.Pp 550The 551.Fn RB_ROOT , 552.Fn RB_MIN , 553.Fn RB_MAX , 554.Fn RB_NEXT , 555and 556.Fn RB_PREV 557macros can be used to traverse the tree: 558.Pp 559.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" 560.Pp 561Or, for simplicity, one can use the 562.Fn RB_FOREACH 563or 564.Fn RB_FOREACH_REVERSE 565macro: 566.Bd -ragged -offset indent 567.Fn RB_FOREACH np NAME head 568.Ed 569.Pp 570The macros 571.Fn RB_FOREACH_SAFE 572and 573.Fn RB_FOREACH_REVERSE_SAFE 574traverse the tree referenced by head 575in a forward or reverse direction respectively, 576assigning each element in turn to np. 577However, unlike their unsafe counterparts, 578they permit both the removal of np 579as well as freeing it from within the loop safely 580without interfering with the traversal. 581.Pp 582Both 583.Fn RB_FOREACH_FROM 584and 585.Fn RB_FOREACH_REVERSE_FROM 586may be used to continue an interrupted traversal 587in a forward or reverse direction respectively. 588The head pointer is not required. 589The pointer to the node from where to resume the traversal 590should be passed as their last argument, 591and will be overwritten to provide safe traversal. 592.Pp 593The 594.Fn RB_EMPTY 595macro should be used to check whether a rank-balanced tree is empty. 596.Pp 597The 598.Fn RB_REINSERT 599macro updates the position of the element 600.Fa elm 601in the tree. 602This must be called if a member of a 603.Nm tree 604is modified in a way that affects comparison, such as by modifying 605a node's key. 606This is a lower overhead alternative to removing the element 607and reinserting it again. 608.Pp 609The 610.Fn RB_AUGMENT 611macro updates augmentation data of the element 612.Fa elm 613in the tree. 614By default, it has no effect. 615It is not meant to be invoked by the RB user. 616If 617.Fn RB_AUGMENT 618is defined by the RB user, then when an element is inserted or removed 619from the tree, it is invoked for every element in the tree that is the 620root of an altered subtree, working from the bottom of the tree up to 621the top. 622It is typically used to maintain some associative accumulation of tree 623elements, such as sums, minima, maxima, and the like. 624.Pp 625The 626.Fn RB_AUGMENT_CHECK 627macro updates augmentation data of the element 628.Fa elm 629in the tree. 630By default, it does nothing and returns false. 631If 632.Fn RB_AUGMENT_CHECK 633is defined, then when an element is inserted or removed from the tree, 634it is invoked for every element in the tree that is the root of an 635altered subtree, working from the bottom of the tree up toward the 636top, until it returns false to indicate that it did not change the 637element and so working further up the tree would change nothing. 638It is typically used to maintain some associative accumulation of tree 639elements, such as sums, minima, maxima, and the like. 640.Pp 641The 642.Fn RB_UPDATE_AUGMENT 643macro updates augmentation data of the element 644.Fa elm 645and its ancestors in the tree. 646If 647.Fn RB_AUGMENT 648is defined by the RB user, then when an element in the 649tree is changed, without changing the order of items in the tree, 650invoking this function on that element restores consistency of the 651augmentation state of the tree as if the element had been removed and 652inserted again. 653.Sh EXAMPLES 654The following example demonstrates how to declare a rank-balanced tree 655holding integers. 656Values are inserted into it and the contents of the tree are printed 657in order. 658To maintain the sum of the values in the tree, each element maintains 659the sum of its value and the sums from its left and right subtrees. 660Lastly, the internal structure of the tree is printed. 661.Bd -literal -offset 3n 662#include <sys/tree.h> 663#include <err.h> 664#include <stdio.h> 665#include <stdlib.h> 666 667struct node { 668 RB_ENTRY(node) entry; 669 int i, sum; 670}; 671 672int 673intcmp(struct node *e1, struct node *e2) 674{ 675 return (e1->i < e2->i ? -1 : e1->i > e2->i); 676} 677 678int 679sumaug(struct node *e) 680{ 681 e->sum = e->i; 682 if (RB_LEFT(e, entry) != NULL) 683 e->sum += RB_LEFT(e, entry)->sum; 684 if (RB_RIGHT(e, entry) != NULL) 685 e->sum += RB_RIGHT(e, entry)->sum; 686} 687#define RB_AUGMENT(entry) sumaug(entry) 688 689RB_HEAD(inttree, node) head = RB_INITIALIZER(&head); 690RB_GENERATE(inttree, node, entry, intcmp) 691 692int testdata[] = { 693 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18, 694 7, 11, 14 695}; 696 697void 698print_tree(struct node *n) 699{ 700 struct node *left, *right; 701 702 if (n == NULL) { 703 printf("nil"); 704 return; 705 } 706 left = RB_LEFT(n, entry); 707 right = RB_RIGHT(n, entry); 708 if (left == NULL && right == NULL) 709 printf("%d", n->i); 710 else { 711 printf("%d(", n->i); 712 print_tree(left); 713 printf(","); 714 print_tree(right); 715 printf(")"); 716 } 717} 718 719int 720main(void) 721{ 722 int i; 723 struct node *n; 724 725 for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) { 726 if ((n = malloc(sizeof(struct node))) == NULL) 727 err(1, NULL); 728 n->i = testdata[i]; 729 RB_INSERT(inttree, &head, n); 730 } 731 732 RB_FOREACH(n, inttree, &head) { 733 printf("%d\en", n->i); 734 } 735 print_tree(RB_ROOT(&head)); 736 printf("Sum of values = %d\n", RB_ROOT(&head)->sum); 737 printf("\en"); 738 return (0); 739} 740.Ed 741.Sh NOTES 742Trying to free a tree in the following way is a common error: 743.Bd -literal -offset indent 744SPLAY_FOREACH(var, NAME, head) { 745 SPLAY_REMOVE(NAME, head, var); 746 free(var); 747} 748free(head); 749.Ed 750.Pp 751Since 752.Va var 753is freed, the 754.Fn FOREACH 755macro refers to a pointer that may have been reallocated already. 756Proper code needs a second variable. 757.Bd -literal -offset indent 758for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { 759 nxt = SPLAY_NEXT(NAME, head, var); 760 SPLAY_REMOVE(NAME, head, var); 761 free(var); 762} 763.Ed 764.Pp 765Both 766.Fn RB_INSERT 767and 768.Fn SPLAY_INSERT 769return 770.Dv NULL 771if the element was inserted in the tree successfully, otherwise they 772return a pointer to the element with the colliding key. 773.Pp 774Accordingly, 775.Fn RB_REMOVE 776and 777.Fn SPLAY_REMOVE 778return the pointer to the removed element otherwise they return 779.Dv NULL 780to indicate an error. 781.Sh SEE ALSO 782.Xr arb 3 , 783.Xr queue 3 784.Rs 785.%A "Bernhard Haeupler" 786.%A "Siddhartha Sen" 787.%A "Robert E. Tarjan" 788.%T "Rank-Balanced Trees" 789.%U "http://sidsen.azurewebsites.net/papers/rb-trees-talg.pdf" 790.%J "ACM Transactions on Algorithms" 791.%V "11" 792.%N "4" 793.%D "June 2015" 794.Re 795.Sh HISTORY 796The tree macros first appeared in 797.Fx 4.6 . 798.Sh AUTHORS 799The author of the tree macros is 800.An Niels Provos . 801