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