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