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