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