187f5f0ecSDag-Erling Smørgrav.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 2480565d5SRuslan Ermilov.\" 3480565d5SRuslan Ermilov.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> 4480565d5SRuslan Ermilov.\" All rights reserved. 5480565d5SRuslan Ermilov.\" 6480565d5SRuslan Ermilov.\" Redistribution and use in source and binary forms, with or without 7480565d5SRuslan Ermilov.\" modification, are permitted provided that the following conditions 8480565d5SRuslan Ermilov.\" are met: 9480565d5SRuslan Ermilov.\" 1. Redistributions of source code must retain the above copyright 10480565d5SRuslan Ermilov.\" notice, this list of conditions and the following disclaimer. 11480565d5SRuslan Ermilov.\" 2. Redistributions in binary form must reproduce the above copyright 12480565d5SRuslan Ermilov.\" notice, this list of conditions and the following disclaimer in the 13480565d5SRuslan Ermilov.\" documentation and/or other materials provided with the distribution. 14480565d5SRuslan Ermilov.\" 3. All advertising materials mentioning features or use of this software 15480565d5SRuslan Ermilov.\" must display the following acknowledgement: 16480565d5SRuslan Ermilov.\" This product includes software developed by Niels Provos. 17480565d5SRuslan Ermilov.\" 4. The name of the author may not be used to endorse or promote products 18480565d5SRuslan Ermilov.\" derived from this software without specific prior written permission. 19480565d5SRuslan Ermilov.\" 20480565d5SRuslan Ermilov.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21480565d5SRuslan Ermilov.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22480565d5SRuslan Ermilov.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23480565d5SRuslan Ermilov.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24480565d5SRuslan Ermilov.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25480565d5SRuslan Ermilov.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26480565d5SRuslan Ermilov.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27480565d5SRuslan Ermilov.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28480565d5SRuslan Ermilov.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29480565d5SRuslan Ermilov.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30480565d5SRuslan Ermilov.\" 31*503b7f94SMaxim Konovalov.Dd August 2, 2024 3287f5f0ecSDag-Erling Smørgrav.Dt TREE 3 3387f5f0ecSDag-Erling Smørgrav.Os 3487f5f0ecSDag-Erling Smørgrav.Sh NAME 3587f5f0ecSDag-Erling Smørgrav.Nm SPLAY_PROTOTYPE , 3687f5f0ecSDag-Erling Smørgrav.Nm SPLAY_GENERATE , 3787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ENTRY , 3887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_HEAD , 3987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INITIALIZER , 4087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_ROOT , 4187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_EMPTY , 4287f5f0ecSDag-Erling Smørgrav.Nm SPLAY_NEXT , 4387f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MIN , 4487f5f0ecSDag-Erling Smørgrav.Nm SPLAY_MAX , 4587f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FIND , 4687f5f0ecSDag-Erling Smørgrav.Nm SPLAY_LEFT , 4787f5f0ecSDag-Erling Smørgrav.Nm SPLAY_RIGHT , 4887f5f0ecSDag-Erling Smørgrav.Nm SPLAY_FOREACH , 4987f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INIT , 5087f5f0ecSDag-Erling Smørgrav.Nm SPLAY_INSERT , 5187f5f0ecSDag-Erling Smørgrav.Nm SPLAY_REMOVE , 5287f5f0ecSDag-Erling Smørgrav.Nm RB_PROTOTYPE , 53d72cd779SJason Evans.Nm RB_PROTOTYPE_STATIC , 5451782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_INSERT , 5551782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_INSERT_COLOR , 5651782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_REMOVE , 5751782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_REMOVE_COLOR , 5851782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_FIND , 5951782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_NFIND , 6051782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_NEXT , 6151782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_PREV , 6251782e3aSKonstantin Belousov.Nm RB_PROTOTYPE_MINMAX , 6322823764SEdward Tomasz Napierala.Nm RB_PROTOTYPE_REINSERT , 6487f5f0ecSDag-Erling Smørgrav.Nm RB_GENERATE , 65d72cd779SJason Evans.Nm RB_GENERATE_STATIC , 6651782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT , 6751782e3aSKonstantin Belousov.Nm RB_GENERATE_INSERT_COLOR , 6851782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE , 6951782e3aSKonstantin Belousov.Nm RB_GENERATE_REMOVE_COLOR , 7051782e3aSKonstantin Belousov.Nm RB_GENERATE_FIND , 7151782e3aSKonstantin Belousov.Nm RB_GENERATE_NFIND , 7251782e3aSKonstantin Belousov.Nm RB_GENERATE_NEXT , 7351782e3aSKonstantin Belousov.Nm RB_GENERATE_PREV , 7451782e3aSKonstantin Belousov.Nm RB_GENERATE_MINMAX , 7522823764SEdward Tomasz Napierala.Nm RB_GENERATE_REINSERT , 7687f5f0ecSDag-Erling Smørgrav.Nm RB_ENTRY , 7787f5f0ecSDag-Erling Smørgrav.Nm RB_HEAD , 7887f5f0ecSDag-Erling Smørgrav.Nm RB_INITIALIZER , 7987f5f0ecSDag-Erling Smørgrav.Nm RB_ROOT , 8087f5f0ecSDag-Erling Smørgrav.Nm RB_EMPTY , 8187f5f0ecSDag-Erling Smørgrav.Nm RB_NEXT , 828e4fd0a1SJason Evans.Nm RB_PREV , 8387f5f0ecSDag-Erling Smørgrav.Nm RB_MIN , 8487f5f0ecSDag-Erling Smørgrav.Nm RB_MAX , 8587f5f0ecSDag-Erling Smørgrav.Nm RB_FIND , 8606115e08SJason Evans.Nm RB_NFIND , 8787f5f0ecSDag-Erling Smørgrav.Nm RB_LEFT , 8887f5f0ecSDag-Erling Smørgrav.Nm RB_RIGHT , 8987f5f0ecSDag-Erling Smørgrav.Nm RB_PARENT , 9087f5f0ecSDag-Erling Smørgrav.Nm RB_FOREACH , 91bff27689SBruce M Simpson.Nm RB_FOREACH_FROM , 929dbae282SGleb Smirnoff.Nm RB_FOREACH_SAFE , 938e4fd0a1SJason Evans.Nm RB_FOREACH_REVERSE , 94bff27689SBruce M Simpson.Nm RB_FOREACH_REVERSE_FROM , 959dbae282SGleb Smirnoff.Nm RB_FOREACH_REVERSE_SAFE , 9687f5f0ecSDag-Erling Smørgrav.Nm RB_INIT , 9787f5f0ecSDag-Erling Smørgrav.Nm RB_INSERT , 98368ee2f8SDoug Moore.Nm RB_INSERT_NEXT , 99368ee2f8SDoug Moore.Nm RB_INSERT_PREV , 10022823764SEdward Tomasz Napierala.Nm RB_REMOVE , 101a8380d27SDoug Moore.Nm RB_REINSERT , 102a8380d27SDoug Moore.Nm RB_AUGMENT 103b16f993eSDoug Moore.Nm RB_AUGMENT_CHECK, 10435557a0dSDoug Moore.Nm RB_UPDATE_AUGMENT 105e605dcc9SDoug Moore.Nd "implementations of splay and rank-balanced (wavl) trees" 10687f5f0ecSDag-Erling Smørgrav.Sh SYNOPSIS 107480565d5SRuslan Ermilov.In sys/tree.h 108480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP 109480565d5SRuslan Ermilov.Fn SPLAY_GENERATE NAME TYPE FIELD CMP 110480565d5SRuslan Ermilov.Fn SPLAY_ENTRY TYPE 111480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 11287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 11387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" 11487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT "SPLAY_HEAD *head" 115480565d5SRuslan Ermilov.Ft bool 11687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY "SPLAY_HEAD *head" 11787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 118480565d5SRuslan Ermilov.Fn SPLAY_NEXT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 11987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 120480565d5SRuslan Ermilov.Fn SPLAY_MIN NAME "SPLAY_HEAD *head" 12187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 122480565d5SRuslan Ermilov.Fn SPLAY_MAX NAME "SPLAY_HEAD *head" 12387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 124480565d5SRuslan Ermilov.Fn SPLAY_FIND NAME "SPLAY_HEAD *head" "struct TYPE *elm" 12587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" 12787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 12887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" 129480565d5SRuslan Ermilov.Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head" 13087f5f0ecSDag-Erling Smørgrav.Ft void 13187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT "SPLAY_HEAD *head" 13287f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 133480565d5SRuslan Ermilov.Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm" 13487f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 135480565d5SRuslan Ermilov.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm" 136480565d5SRuslan Ermilov.Fn RB_PROTOTYPE NAME TYPE FIELD CMP 137d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP 13851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR 13951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR 14051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR 14151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR 14251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR 14351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR 14451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR 14551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR 14651782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR 14722823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT NAME TYPE ATTR 148480565d5SRuslan Ermilov.Fn RB_GENERATE NAME TYPE FIELD CMP 149d72cd779SJason Evans.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP 15051782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR 15151782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR 15251782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR 15351782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR 15451782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR 15551782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR 15651782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR 15751782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR 15851782e3aSKonstantin Belousov.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR 15922823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR 160480565d5SRuslan Ermilov.Fn RB_ENTRY TYPE 161480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 16287f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER "RB_HEAD *head" 16387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 16487f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT "RB_HEAD *head" 16587f5f0ecSDag-Erling Smørgrav.Ft "bool" 16687f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY "RB_HEAD *head" 16787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 168480565d5SRuslan Ermilov.Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" 16987f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 1708e4fd0a1SJason Evans.Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm" 1718e4fd0a1SJason Evans.Ft "struct TYPE *" 172480565d5SRuslan Ermilov.Fn RB_MIN NAME "RB_HEAD *head" 17387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 174480565d5SRuslan Ermilov.Fn RB_MAX NAME "RB_HEAD *head" 17587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 176480565d5SRuslan Ermilov.Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm" 17787f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 17806115e08SJason Evans.Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm" 17906115e08SJason Evans.Ft "struct TYPE *" 18087f5f0ecSDag-Erling Smørgrav.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" 18187f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 18287f5f0ecSDag-Erling Smørgrav.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" 18387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 18487f5f0ecSDag-Erling Smørgrav.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" 185480565d5SRuslan Ermilov.Fn RB_FOREACH VARNAME NAME "RB_HEAD *head" 186639bf7bdSBruce M Simpson.Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" 1879dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 1888e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head" 189639bf7bdSBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" 1909dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" 19187f5f0ecSDag-Erling Smørgrav.Ft void 19287f5f0ecSDag-Erling Smørgrav.Fn RB_INIT "RB_HEAD *head" 19387f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 194480565d5SRuslan Ermilov.Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm" 19587f5f0ecSDag-Erling Smørgrav.Ft "struct TYPE *" 196368ee2f8SDoug Moore.Fn RB_INSERT_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" "struct TYPE *next" 197368ee2f8SDoug Moore.Ft "struct TYPE *" 198368ee2f8SDoug Moore.Fn RB_INSERT_PREV NAME "RB_HEAD *head" "struct TYPE *elm" "struct TYPE *prev" 199368ee2f8SDoug Moore.Ft "struct TYPE *" 200480565d5SRuslan Ermilov.Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm" 20122823764SEdward Tomasz Napierala.Ft "struct TYPE *" 20222823764SEdward Tomasz Napierala.Fn RB_REINSERT NAME "RB_HEAD *head" "struct TYPE *elm" 203a8380d27SDoug Moore.Ft "void" 204a8380d27SDoug Moore.Fn RB_AUGMENT NAME "struct TYPE *elm" 205b16f993eSDoug Moore.Ft "bool" 206b16f993eSDoug Moore.Fn RB_AUGMENT_CHECK NAME "struct TYPE *elm" 20735557a0dSDoug Moore.Ft "void" 20835557a0dSDoug Moore.Fn RB_UPDATE_AUGMENT NAME "struct TYPE *elm" 20987f5f0ecSDag-Erling Smørgrav.Sh DESCRIPTION 210480565d5SRuslan ErmilovThese macros define data structures for different types of trees: 211e605dcc9SDoug Mooresplay trees and rank-balanced (wavl) trees. 21287f5f0ecSDag-Erling Smørgrav.Pp 21387f5f0ecSDag-Erling SmørgravIn the macro definitions, 21487f5f0ecSDag-Erling Smørgrav.Fa TYPE 21587f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must contain a field of type 216480565d5SRuslan Ermilov.Vt SPLAY_ENTRY , 21787f5f0ecSDag-Erling Smørgravor 218480565d5SRuslan Ermilov.Vt RB_ENTRY , 21987f5f0ecSDag-Erling Smørgravnamed 22087f5f0ecSDag-Erling Smørgrav.Fa ENTRYNAME . 22187f5f0ecSDag-Erling SmørgravThe argument 22287f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 22387f5f0ecSDag-Erling Smørgravis the name tag of a user defined structure that must be declared 22487f5f0ecSDag-Erling Smørgravusing the macros 22587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD , 22687f5f0ecSDag-Erling Smørgravor 22787f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD . 22887f5f0ecSDag-Erling SmørgravThe argument 22987f5f0ecSDag-Erling Smørgrav.Fa NAME 23087f5f0ecSDag-Erling Smørgravhas to be a unique name prefix for every tree that is defined. 23187f5f0ecSDag-Erling Smørgrav.Pp 232d72cd779SJason EvansThe function prototypes are declared with 233480565d5SRuslan Ermilov.Fn SPLAY_PROTOTYPE , 234d72cd779SJason Evans.Fn RB_PROTOTYPE , 23587f5f0ecSDag-Erling Smørgravor 236d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC . 237d72cd779SJason EvansThe function bodies are generated with 238480565d5SRuslan Ermilov.Fn SPLAY_GENERATE , 239d72cd779SJason Evans.Fn RB_GENERATE , 24087f5f0ecSDag-Erling Smørgravor 241d72cd779SJason Evans.Fn RB_GENERATE_STATIC . 24287f5f0ecSDag-Erling SmørgravSee the examples below for further explanation of how these macros are used. 24387f5f0ecSDag-Erling Smørgrav.Sh SPLAY TREES 244480565d5SRuslan ErmilovA splay tree is a self-organizing data structure. 245480565d5SRuslan ErmilovEvery operation on the tree causes a splay to happen. 246480565d5SRuslan ErmilovThe splay moves the requested 24787f5f0ecSDag-Erling Smørgravnode to the root of the tree and partly rebalances it. 24887f5f0ecSDag-Erling Smørgrav.Pp 24987f5f0ecSDag-Erling SmørgravThis has the benefit that request locality causes faster lookups as 250480565d5SRuslan Ermilovthe requested nodes move to the top of the tree. 251480565d5SRuslan ErmilovOn the other hand, every lookup causes memory writes. 25287f5f0ecSDag-Erling Smørgrav.Pp 253480565d5SRuslan ErmilovThe Balance Theorem bounds the total access time for 254480565d5SRuslan Ermilov.Ar m 255480565d5SRuslan Ermilovoperations and 256480565d5SRuslan Ermilov.Ar n 257480565d5SRuslan Ermilovinserts on an initially empty tree as 258480565d5SRuslan Ermilov.Fn O "\*[lp]m + n\*[rp]lg n" . 259480565d5SRuslan ErmilovThe 260480565d5SRuslan Ermilovamortized cost for a sequence of 261480565d5SRuslan Ermilov.Ar m 262480565d5SRuslan Ermilovaccesses to a splay tree is 263480565d5SRuslan Ermilov.Fn O "lg n" . 26487f5f0ecSDag-Erling Smørgrav.Pp 26587f5f0ecSDag-Erling SmørgravA splay tree is headed by a structure defined by the 26687f5f0ecSDag-Erling Smørgrav.Fn SPLAY_HEAD 26787f5f0ecSDag-Erling Smørgravmacro. 26887f5f0ecSDag-Erling SmørgravA 26987f5f0ecSDag-Erling Smørgravstructure is declared as follows: 270480565d5SRuslan Ermilov.Bd -ragged -offset indent 271480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 272480565d5SRuslan Ermilov.Va head ; 27387f5f0ecSDag-Erling Smørgrav.Ed 27487f5f0ecSDag-Erling Smørgrav.Pp 27587f5f0ecSDag-Erling Smørgravwhere 27687f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 27787f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 27887f5f0ecSDag-Erling Smørgrav.Fa TYPE 27987f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 28087f5f0ecSDag-Erling Smørgrav.Pp 28187f5f0ecSDag-Erling SmørgravThe 28287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY 28387f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 28487f5f0ecSDag-Erling Smørgrav.Pp 28587f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 28687f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 28787f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 28887f5f0ecSDag-Erling Smørgravmacro, 28987f5f0ecSDag-Erling Smørgravwhere 29087f5f0ecSDag-Erling Smørgrav.Fa NAME 29187f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 29287f5f0ecSDag-Erling SmørgravThe 29387f5f0ecSDag-Erling Smørgrav.Fa TYPE 29487f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 29587f5f0ecSDag-Erling Smørgravby the tree. 29687f5f0ecSDag-Erling SmørgravThe 29787f5f0ecSDag-Erling Smørgrav.Fa FIELD 29887f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 29987f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ENTRY . 30087f5f0ecSDag-Erling Smørgrav.Pp 30187f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 30287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_GENERATE 303480565d5SRuslan Ermilovmacro. 304480565d5SRuslan ErmilovIt takes the same arguments as the 30587f5f0ecSDag-Erling Smørgrav.Fn SPLAY_PROTOTYPE 30687f5f0ecSDag-Erling Smørgravmacro, but should be used only once. 30787f5f0ecSDag-Erling Smørgrav.Pp 30887f5f0ecSDag-Erling SmørgravFinally, 30987f5f0ecSDag-Erling Smørgravthe 31087f5f0ecSDag-Erling Smørgrav.Fa CMP 311480565d5SRuslan Ermilovargument is the name of a function used to compare tree nodes 312480565d5SRuslan Ermilovwith each other. 313480565d5SRuslan ErmilovThe function takes two arguments of type 314480565d5SRuslan Ermilov.Vt "struct TYPE *" . 31587f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 316480565d5SRuslan Ermilovvalue smaller than zero. 317480565d5SRuslan ErmilovIf they are equal, the function returns zero. 318480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero. 319480565d5SRuslan ErmilovThe compare 32087f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 32187f5f0ecSDag-Erling Smørgrav.Pp 32287f5f0ecSDag-Erling SmørgravThe 32387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INIT 32487f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 32587f5f0ecSDag-Erling Smørgrav.Fa head . 32687f5f0ecSDag-Erling Smørgrav.Pp 32787f5f0ecSDag-Erling SmørgravThe splay tree can also be initialized statically by using the 32887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INITIALIZER 32987f5f0ecSDag-Erling Smørgravmacro like this: 330480565d5SRuslan Ermilov.Bd -ragged -offset indent 331480565d5SRuslan Ermilov.Fn SPLAY_HEAD HEADNAME TYPE 332480565d5SRuslan Ermilov.Va head 333480565d5SRuslan Ermilov= 334480565d5SRuslan Ermilov.Fn SPLAY_INITIALIZER &head ; 33587f5f0ecSDag-Erling Smørgrav.Ed 33687f5f0ecSDag-Erling Smørgrav.Pp 33787f5f0ecSDag-Erling SmørgravThe 33887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 33987f5f0ecSDag-Erling Smørgravmacro inserts the new element 34087f5f0ecSDag-Erling Smørgrav.Fa elm 34187f5f0ecSDag-Erling Smørgravinto the tree. 34287f5f0ecSDag-Erling Smørgrav.Pp 34387f5f0ecSDag-Erling SmørgravThe 34487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 34587f5f0ecSDag-Erling Smørgravmacro removes the element 34687f5f0ecSDag-Erling Smørgrav.Fa elm 34787f5f0ecSDag-Erling Smørgravfrom the tree pointed by 34887f5f0ecSDag-Erling Smørgrav.Fa head . 34987f5f0ecSDag-Erling Smørgrav.Pp 35087f5f0ecSDag-Erling SmørgravThe 35187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FIND 35287f5f0ecSDag-Erling Smørgravmacro can be used to find a particular element in the tree. 35387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 35487f5f0ecSDag-Erling Smørgravstruct TYPE find, *res; 35587f5f0ecSDag-Erling Smørgravfind.key = 30; 35687f5f0ecSDag-Erling Smørgravres = SPLAY_FIND(NAME, head, &find); 35787f5f0ecSDag-Erling Smørgrav.Ed 35887f5f0ecSDag-Erling Smørgrav.Pp 35987f5f0ecSDag-Erling SmørgravThe 36087f5f0ecSDag-Erling Smørgrav.Fn SPLAY_ROOT , 36187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MIN , 36287f5f0ecSDag-Erling Smørgrav.Fn SPLAY_MAX , 36387f5f0ecSDag-Erling Smørgravand 36487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_NEXT 36587f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 36687f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 36787f5f0ecSDag-Erling Smørgravfor (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) 36887f5f0ecSDag-Erling Smørgrav.Ed 36987f5f0ecSDag-Erling Smørgrav.Pp 37087f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 37187f5f0ecSDag-Erling Smørgrav.Fn SPLAY_FOREACH 37287f5f0ecSDag-Erling Smørgravmacro: 373480565d5SRuslan Ermilov.Bd -ragged -offset indent 374480565d5SRuslan Ermilov.Fn SPLAY_FOREACH np NAME head 37587f5f0ecSDag-Erling Smørgrav.Ed 37687f5f0ecSDag-Erling Smørgrav.Pp 37787f5f0ecSDag-Erling SmørgravThe 37887f5f0ecSDag-Erling Smørgrav.Fn SPLAY_EMPTY 37987f5f0ecSDag-Erling Smørgravmacro should be used to check whether a splay tree is empty. 380e605dcc9SDoug Moore.Sh RANK-BALANCED TREES 381e605dcc9SDoug MooreRank-balanced (RB) trees are a framework for defining height-balanced 382e605dcc9SDoug Moorebinary search trees, including AVL and red-black trees. 383e605dcc9SDoug MooreEach tree node has an associated rank. 384e605dcc9SDoug MooreBalance conditions are expressed by conditions on the differences in 385e605dcc9SDoug Moorerank between any node and its children. 386e605dcc9SDoug MooreRank differences are stored in each tree node. 38787f5f0ecSDag-Erling Smørgrav.Pp 388e605dcc9SDoug MooreThe balance conditions implemented by the RB macros lead to weak AVL 389e605dcc9SDoug Moore(wavl) trees, which combine the best aspects of AVL and red-black 390e605dcc9SDoug Mooretrees. 391e605dcc9SDoug MooreWavl trees rebalance after an insertion in the same way AVL trees do, 392e605dcc9SDoug Moorewith the same worst-case time as red-black trees offer, and with 393e605dcc9SDoug Moorebetter balance in the resulting tree. 394e605dcc9SDoug MooreWavl trees rebalance after a removal in a way that requires less 395e605dcc9SDoug Moorerestructuring, in the worst case, than either AVL or red-black trees 39658f5de0dSMateusz Piotrowskido. 39758f5de0dSMateusz PiotrowskiRemovals can lead to a tree almost as unbalanced as a red-black 398e605dcc9SDoug Mooretree; insertions lead to a tree becoming as balanced as an AVL tree. 39987f5f0ecSDag-Erling Smørgrav.Pp 400e605dcc9SDoug MooreA rank-balanced tree is headed by a structure defined by the 40187f5f0ecSDag-Erling Smørgrav.Fn RB_HEAD 40287f5f0ecSDag-Erling Smørgravmacro. 40387f5f0ecSDag-Erling SmørgravA 40487f5f0ecSDag-Erling Smørgravstructure is declared as follows: 405480565d5SRuslan Ermilov.Bd -ragged -offset indent 406480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 407480565d5SRuslan Ermilov.Va head ; 40887f5f0ecSDag-Erling Smørgrav.Ed 40987f5f0ecSDag-Erling Smørgrav.Pp 41087f5f0ecSDag-Erling Smørgravwhere 41187f5f0ecSDag-Erling Smørgrav.Fa HEADNAME 41287f5f0ecSDag-Erling Smørgravis the name of the structure to be defined, and struct 41387f5f0ecSDag-Erling Smørgrav.Fa TYPE 41487f5f0ecSDag-Erling Smørgravis the type of the elements to be inserted into the tree. 41587f5f0ecSDag-Erling Smørgrav.Pp 41687f5f0ecSDag-Erling SmørgravThe 41787f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY 41887f5f0ecSDag-Erling Smørgravmacro declares a structure that allows elements to be connected in the tree. 41987f5f0ecSDag-Erling Smørgrav.Pp 42087f5f0ecSDag-Erling SmørgravIn order to use the functions that manipulate the tree structure, 42187f5f0ecSDag-Erling Smørgravtheir prototypes need to be declared with the 42287f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 423d72cd779SJason Evansor 424d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC 42587f5f0ecSDag-Erling Smørgravmacro, 42687f5f0ecSDag-Erling Smørgravwhere 42787f5f0ecSDag-Erling Smørgrav.Fa NAME 42887f5f0ecSDag-Erling Smørgravis a unique identifier for this particular tree. 42987f5f0ecSDag-Erling SmørgravThe 43087f5f0ecSDag-Erling Smørgrav.Fa TYPE 43187f5f0ecSDag-Erling Smørgravargument is the type of the structure that is being managed 43287f5f0ecSDag-Erling Smørgravby the tree. 43387f5f0ecSDag-Erling SmørgravThe 43487f5f0ecSDag-Erling Smørgrav.Fa FIELD 43587f5f0ecSDag-Erling Smørgravargument is the name of the element defined by 43687f5f0ecSDag-Erling Smørgrav.Fn RB_ENTRY . 43751782e3aSKonstantin BelousovIndividual prototypes can be declared with 43851782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT , 43951782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_INSERT_COLOR , 44051782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE , 44151782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_REMOVE_COLOR , 44251782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_FIND , 44351782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NFIND , 44451782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_NEXT , 44551782e3aSKonstantin Belousov.Fn RB_PROTOTYPE_PREV , 44622823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_MINMAX , 44751782e3aSKonstantin Belousovand 44822823764SEdward Tomasz Napierala.Fn RB_PROTOTYPE_REINSERT 449eb49a6d3SEdward Tomasz Napieralain case not all functions are required. 450eb49a6d3SEdward Tomasz NapieralaThe individual prototype macros expect 45151782e3aSKonstantin Belousov.Fa NAME , 45251782e3aSKonstantin Belousov.Fa TYPE , 45351782e3aSKonstantin Belousovand 45451782e3aSKonstantin Belousov.Fa ATTR 455eb49a6d3SEdward Tomasz Napieralaarguments. 456eb49a6d3SEdward Tomasz NapieralaThe 45751782e3aSKonstantin Belousov.Fa ATTR 45851782e3aSKonstantin Belousovargument must be empty for global functions or 45951782e3aSKonstantin Belousov.Fa static 46051782e3aSKonstantin Belousovfor static functions. 46187f5f0ecSDag-Erling Smørgrav.Pp 46287f5f0ecSDag-Erling SmørgravThe function bodies are generated with the 46387f5f0ecSDag-Erling Smørgrav.Fn RB_GENERATE 464d72cd779SJason Evansor 465d72cd779SJason Evans.Fn RB_GENERATE_STATIC 466480565d5SRuslan Ermilovmacro. 467d72cd779SJason EvansThese macros take the same arguments as the 46887f5f0ecSDag-Erling Smørgrav.Fn RB_PROTOTYPE 469d72cd779SJason Evansand 470d72cd779SJason Evans.Fn RB_PROTOTYPE_STATIC 471d72cd779SJason Evansmacros, but should be used only once. 47251782e3aSKonstantin BelousovAs an alternative individual function bodies are generated with the 47351782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT , 47451782e3aSKonstantin Belousov.Fn RB_GENERATE_INSERT_COLOR , 47551782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE , 47651782e3aSKonstantin Belousov.Fn RB_GENERATE_REMOVE_COLOR , 47751782e3aSKonstantin Belousov.Fn RB_GENERATE_FIND , 47851782e3aSKonstantin Belousov.Fn RB_GENERATE_NFIND , 47951782e3aSKonstantin Belousov.Fn RB_GENERATE_NEXT , 48051782e3aSKonstantin Belousov.Fn RB_GENERATE_PREV , 48122823764SEdward Tomasz Napierala.Fn RB_GENERATE_MINMAX , 48251782e3aSKonstantin Belousovand 48322823764SEdward Tomasz Napierala.Fn RB_GENERATE_REINSERT 48451782e3aSKonstantin Belousovmacros. 48587f5f0ecSDag-Erling Smørgrav.Pp 48687f5f0ecSDag-Erling SmørgravFinally, 48787f5f0ecSDag-Erling Smørgravthe 48887f5f0ecSDag-Erling Smørgrav.Fa CMP 4899d44cd42SBenno Riceargument is the name of a function used to compare tree nodes 490480565d5SRuslan Ermilovwith each other. 491480565d5SRuslan ErmilovThe function takes two arguments of type 492480565d5SRuslan Ermilov.Vt "struct TYPE *" . 49387f5f0ecSDag-Erling SmørgravIf the first argument is smaller than the second, the function returns a 494480565d5SRuslan Ermilovvalue smaller than zero. 495480565d5SRuslan ErmilovIf they are equal, the function returns zero. 496480565d5SRuslan ErmilovOtherwise, it should return a value greater than zero. 497480565d5SRuslan ErmilovThe compare 49887f5f0ecSDag-Erling Smørgravfunction defines the order of the tree elements. 49987f5f0ecSDag-Erling Smørgrav.Pp 50087f5f0ecSDag-Erling SmørgravThe 50187f5f0ecSDag-Erling Smørgrav.Fn RB_INIT 50287f5f0ecSDag-Erling Smørgravmacro initializes the tree referenced by 50387f5f0ecSDag-Erling Smørgrav.Fa head . 50487f5f0ecSDag-Erling Smørgrav.Pp 505e605dcc9SDoug MooreThe rank-balanced tree can also be initialized statically by using the 50687f5f0ecSDag-Erling Smørgrav.Fn RB_INITIALIZER 50787f5f0ecSDag-Erling Smørgravmacro like this: 508480565d5SRuslan Ermilov.Bd -ragged -offset indent 509480565d5SRuslan Ermilov.Fn RB_HEAD HEADNAME TYPE 510480565d5SRuslan Ermilov.Va head 511480565d5SRuslan Ermilov= 512480565d5SRuslan Ermilov.Fn RB_INITIALIZER &head ; 51387f5f0ecSDag-Erling Smørgrav.Ed 51487f5f0ecSDag-Erling Smørgrav.Pp 51587f5f0ecSDag-Erling SmørgravThe 51687f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 51787f5f0ecSDag-Erling Smørgravmacro inserts the new element 51887f5f0ecSDag-Erling Smørgrav.Fa elm 51987f5f0ecSDag-Erling Smørgravinto the tree. 52087f5f0ecSDag-Erling Smørgrav.Pp 52187f5f0ecSDag-Erling SmørgravThe 522368ee2f8SDoug Moore.Fn RB_INSERT_NEXT 523368ee2f8SDoug Mooremacro inserts the new element 524368ee2f8SDoug Moore.Fa elm 525368ee2f8SDoug Mooreinto the tree immediately after a given element. 526368ee2f8SDoug Moore.Pp 527368ee2f8SDoug MooreThe 528368ee2f8SDoug Moore.Fn RB_INSERT_PREV 529368ee2f8SDoug Mooremacro inserts the new element 530368ee2f8SDoug Moore.Fa elm 531368ee2f8SDoug Mooreinto the tree immediately before a given element. 532368ee2f8SDoug Moore.Pp 533368ee2f8SDoug MooreThe 53487f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 53587f5f0ecSDag-Erling Smørgravmacro removes the element 53687f5f0ecSDag-Erling Smørgrav.Fa elm 53787f5f0ecSDag-Erling Smørgravfrom the tree pointed by 53887f5f0ecSDag-Erling Smørgrav.Fa head . 53987f5f0ecSDag-Erling Smørgrav.Pp 54087f5f0ecSDag-Erling SmørgravThe 54187f5f0ecSDag-Erling Smørgrav.Fn RB_FIND 54206115e08SJason Evansand 54306115e08SJason Evans.Fn RB_NFIND 54406115e08SJason Evansmacros can be used to find a particular element in the tree. 54508349b18SKonstantin Belousov.Pp 54608349b18SKonstantin BelousovThe 54708349b18SKonstantin Belousov.Fn RB_FIND 54808349b18SKonstantin Belousovmacro returns the element in the tree equal to the provided 54908349b18SKonstantin Belousovkey, or 55008349b18SKonstantin Belousov.Dv NULL 55108349b18SKonstantin Belousovif there is no such element. 55208349b18SKonstantin Belousov.Pp 55308349b18SKonstantin BelousovThe 55408349b18SKonstantin Belousov.Fn RB_NFIND 55508349b18SKonstantin Belousovmacro returns the least element greater than or equal to the provided 55608349b18SKonstantin Belousovkey, or 55708349b18SKonstantin Belousov.Dv NULL 55808349b18SKonstantin Belousovif there is no such element. 55987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 56008349b18SKonstantin Belousovstruct TYPE find, *res, *resn; 56187f5f0ecSDag-Erling Smørgravfind.key = 30; 56287f5f0ecSDag-Erling Smørgravres = RB_FIND(NAME, head, &find); 56308349b18SKonstantin Belousovresn = RB_NFIND(NAME, head, &find); 56487f5f0ecSDag-Erling Smørgrav.Ed 56587f5f0ecSDag-Erling Smørgrav.Pp 56687f5f0ecSDag-Erling SmørgravThe 56787f5f0ecSDag-Erling Smørgrav.Fn RB_ROOT , 56887f5f0ecSDag-Erling Smørgrav.Fn RB_MIN , 56987f5f0ecSDag-Erling Smørgrav.Fn RB_MAX , 5708e4fd0a1SJason Evans.Fn RB_NEXT , 57187f5f0ecSDag-Erling Smørgravand 5728e4fd0a1SJason Evans.Fn RB_PREV 57387f5f0ecSDag-Erling Smørgravmacros can be used to traverse the tree: 574480565d5SRuslan Ermilov.Pp 575480565d5SRuslan Ermilov.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" 57687f5f0ecSDag-Erling Smørgrav.Pp 57787f5f0ecSDag-Erling SmørgravOr, for simplicity, one can use the 57887f5f0ecSDag-Erling Smørgrav.Fn RB_FOREACH 5798e4fd0a1SJason Evansor 5808e4fd0a1SJason Evans.Fn RB_FOREACH_REVERSE 58187f5f0ecSDag-Erling Smørgravmacro: 582480565d5SRuslan Ermilov.Bd -ragged -offset indent 583480565d5SRuslan Ermilov.Fn RB_FOREACH np NAME head 58487f5f0ecSDag-Erling Smørgrav.Ed 58587f5f0ecSDag-Erling Smørgrav.Pp 5869dbae282SGleb SmirnoffThe macros 5879dbae282SGleb Smirnoff.Fn RB_FOREACH_SAFE 5889dbae282SGleb Smirnoffand 5899dbae282SGleb Smirnoff.Fn RB_FOREACH_REVERSE_SAFE 5909dbae282SGleb Smirnofftraverse the tree referenced by head 5919dbae282SGleb Smirnoffin a forward or reverse direction respectively, 5929dbae282SGleb Smirnoffassigning each element in turn to np. 5939dbae282SGleb SmirnoffHowever, unlike their unsafe counterparts, 5949dbae282SGleb Smirnoffthey permit both the removal of np 5959dbae282SGleb Smirnoffas well as freeing it from within the loop safely 5969dbae282SGleb Smirnoffwithout interfering with the traversal. 5979dbae282SGleb Smirnoff.Pp 598bff27689SBruce M SimpsonBoth 599bff27689SBruce M Simpson.Fn RB_FOREACH_FROM 600bff27689SBruce M Simpsonand 601bff27689SBruce M Simpson.Fn RB_FOREACH_REVERSE_FROM 602bff27689SBruce M Simpsonmay be used to continue an interrupted traversal 603bff27689SBruce M Simpsonin a forward or reverse direction respectively. 604639bf7bdSBruce M SimpsonThe head pointer is not required. 605639bf7bdSBruce M SimpsonThe pointer to the node from where to resume the traversal 606639bf7bdSBruce M Simpsonshould be passed as their last argument, 607bff27689SBruce M Simpsonand will be overwritten to provide safe traversal. 608bff27689SBruce M Simpson.Pp 60987f5f0ecSDag-Erling SmørgravThe 61087f5f0ecSDag-Erling Smørgrav.Fn RB_EMPTY 611e605dcc9SDoug Mooremacro should be used to check whether a rank-balanced tree is empty. 61222823764SEdward Tomasz Napierala.Pp 61322823764SEdward Tomasz NapieralaThe 61422823764SEdward Tomasz Napierala.Fn RB_REINSERT 61522823764SEdward Tomasz Napieralamacro updates the position of the element 61622823764SEdward Tomasz Napierala.Fa elm 61722823764SEdward Tomasz Napieralain the tree. 61822823764SEdward Tomasz NapieralaThis must be called if a member of a 61922823764SEdward Tomasz Napierala.Nm tree 62022823764SEdward Tomasz Napieralais modified in a way that affects comparison, such as by modifying 62122823764SEdward Tomasz Napieralaa node's key. 62222823764SEdward Tomasz NapieralaThis is a lower overhead alternative to removing the element 62322823764SEdward Tomasz Napieralaand reinserting it again. 624a8380d27SDoug Moore.Pp 625a8380d27SDoug MooreThe 626a8380d27SDoug Moore.Fn RB_AUGMENT 627a8380d27SDoug Mooremacro updates augmentation data of the element 628a8380d27SDoug Moore.Fa elm 629a8380d27SDoug Moorein the tree. 630a8380d27SDoug MooreBy default, it has no effect. 631a8380d27SDoug MooreIt is not meant to be invoked by the RB user. 63235557a0dSDoug MooreIf 63335557a0dSDoug Moore.Fn RB_AUGMENT 63435557a0dSDoug Mooreis defined by the RB user, then when an element is inserted or removed 63535557a0dSDoug Moorefrom the tree, it is invoked for every element in the tree that is the 63635557a0dSDoug Mooreroot of an altered subtree, working from the bottom of the tree up to 63735557a0dSDoug Moorethe top. 638a8380d27SDoug MooreIt is typically used to maintain some associative accumulation of tree 639a8380d27SDoug Mooreelements, such as sums, minima, maxima, and the like. 64035557a0dSDoug Moore.Pp 64135557a0dSDoug MooreThe 642b16f993eSDoug Moore.Fn RB_AUGMENT_CHECK 643b16f993eSDoug Mooremacro updates augmentation data of the element 644b16f993eSDoug Moore.Fa elm 645b16f993eSDoug Moorein the tree. 646b16f993eSDoug MooreBy default, it does nothing and returns false. 647b16f993eSDoug MooreIf 648b16f993eSDoug Moore.Fn RB_AUGMENT_CHECK 649b16f993eSDoug Mooreis defined, then when an element is inserted or removed from the tree, 650b16f993eSDoug Mooreit is invoked for every element in the tree that is the root of an 651b16f993eSDoug Moorealtered subtree, working from the bottom of the tree up toward the 652b16f993eSDoug Mooretop, until it returns false to indicate that it did not change the 653b16f993eSDoug Mooreelement and so working further up the tree would change nothing. 654b16f993eSDoug MooreIt is typically used to maintain some associative accumulation of tree 655b16f993eSDoug Mooreelements, such as sums, minima, maxima, and the like. 656b16f993eSDoug Moore.Pp 657b16f993eSDoug MooreThe 65835557a0dSDoug Moore.Fn RB_UPDATE_AUGMENT 65935557a0dSDoug Mooremacro updates augmentation data of the element 66035557a0dSDoug Moore.Fa elm 66135557a0dSDoug Mooreand its ancestors in the tree. 662624e5dc0SKonstantin BelousovIf 663624e5dc0SKonstantin Belousov.Fn RB_AUGMENT 664624e5dc0SKonstantin Belousovis defined by the RB user, then when an element in the 66535557a0dSDoug Mooretree is changed, without changing the order of items in the tree, 66635557a0dSDoug Mooreinvoking this function on that element restores consistency of the 66735557a0dSDoug Mooreaugmentation state of the tree as if the element had been removed and 66835557a0dSDoug Mooreinserted again. 669ac0879c3SEdward Tomasz Napierala.Sh EXAMPLES 670e605dcc9SDoug MooreThe following example demonstrates how to declare a rank-balanced tree 671ac0879c3SEdward Tomasz Napieralaholding integers. 672ac0879c3SEdward Tomasz NapieralaValues are inserted into it and the contents of the tree are printed 673ac0879c3SEdward Tomasz Napieralain order. 674a8380d27SDoug MooreTo maintain the sum of the values in the tree, each element maintains 675a8380d27SDoug Moorethe sum of its value and the sums from its left and right subtrees. 676ac0879c3SEdward Tomasz NapieralaLastly, the internal structure of the tree is printed. 677ac0879c3SEdward Tomasz Napierala.Bd -literal -offset 3n 678*503b7f94SMaxim Konovalov#define RB_AUGMENT(entry) sumaug(entry) 679*503b7f94SMaxim Konovalov 680ac0879c3SEdward Tomasz Napierala#include <sys/tree.h> 681ac0879c3SEdward Tomasz Napierala#include <err.h> 682ac0879c3SEdward Tomasz Napierala#include <stdio.h> 683ac0879c3SEdward Tomasz Napierala#include <stdlib.h> 684ac0879c3SEdward Tomasz Napierala 685ac0879c3SEdward Tomasz Napieralastruct node { 686ac0879c3SEdward Tomasz Napierala RB_ENTRY(node) entry; 687a8380d27SDoug Moore int i, sum; 688ac0879c3SEdward Tomasz Napierala}; 689ac0879c3SEdward Tomasz Napierala 690ac0879c3SEdward Tomasz Napieralaint 691ac0879c3SEdward Tomasz Napieralaintcmp(struct node *e1, struct node *e2) 692ac0879c3SEdward Tomasz Napierala{ 693ac0879c3SEdward Tomasz Napierala return (e1->i < e2->i ? -1 : e1->i > e2->i); 694ac0879c3SEdward Tomasz Napierala} 695ac0879c3SEdward Tomasz Napierala 696*503b7f94SMaxim Konovalovvoid 697a8380d27SDoug Mooresumaug(struct node *e) 698a8380d27SDoug Moore{ 699a8380d27SDoug Moore e->sum = e->i; 700a8380d27SDoug Moore if (RB_LEFT(e, entry) != NULL) 701a8380d27SDoug Moore e->sum += RB_LEFT(e, entry)->sum; 702a8380d27SDoug Moore if (RB_RIGHT(e, entry) != NULL) 703a8380d27SDoug Moore e->sum += RB_RIGHT(e, entry)->sum; 704a8380d27SDoug Moore} 705a8380d27SDoug Moore 706ac0879c3SEdward Tomasz NapieralaRB_HEAD(inttree, node) head = RB_INITIALIZER(&head); 707ac0879c3SEdward Tomasz NapieralaRB_GENERATE(inttree, node, entry, intcmp) 708ac0879c3SEdward Tomasz Napierala 709ac0879c3SEdward Tomasz Napieralaint testdata[] = { 710ac0879c3SEdward Tomasz Napierala 20, 16, 17, 13, 3, 6, 1, 8, 2, 4, 10, 19, 5, 9, 12, 15, 18, 711ac0879c3SEdward Tomasz Napierala 7, 11, 14 712ac0879c3SEdward Tomasz Napierala}; 713ac0879c3SEdward Tomasz Napierala 714ac0879c3SEdward Tomasz Napieralavoid 715ac0879c3SEdward Tomasz Napieralaprint_tree(struct node *n) 716ac0879c3SEdward Tomasz Napierala{ 717ac0879c3SEdward Tomasz Napierala struct node *left, *right; 718ac0879c3SEdward Tomasz Napierala 719ac0879c3SEdward Tomasz Napierala if (n == NULL) { 720ac0879c3SEdward Tomasz Napierala printf("nil"); 721ac0879c3SEdward Tomasz Napierala return; 722ac0879c3SEdward Tomasz Napierala } 723ac0879c3SEdward Tomasz Napierala left = RB_LEFT(n, entry); 724ac0879c3SEdward Tomasz Napierala right = RB_RIGHT(n, entry); 725ac0879c3SEdward Tomasz Napierala if (left == NULL && right == NULL) 726ac0879c3SEdward Tomasz Napierala printf("%d", n->i); 727ac0879c3SEdward Tomasz Napierala else { 728ac0879c3SEdward Tomasz Napierala printf("%d(", n->i); 729ac0879c3SEdward Tomasz Napierala print_tree(left); 730ac0879c3SEdward Tomasz Napierala printf(","); 731ac0879c3SEdward Tomasz Napierala print_tree(right); 732ac0879c3SEdward Tomasz Napierala printf(")"); 733ac0879c3SEdward Tomasz Napierala } 734ac0879c3SEdward Tomasz Napierala} 735ac0879c3SEdward Tomasz Napierala 736ac0879c3SEdward Tomasz Napieralaint 737ac0879c3SEdward Tomasz Napieralamain(void) 738ac0879c3SEdward Tomasz Napierala{ 739ac0879c3SEdward Tomasz Napierala int i; 740ac0879c3SEdward Tomasz Napierala struct node *n; 741ac0879c3SEdward Tomasz Napierala 742ac0879c3SEdward Tomasz Napierala for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) { 743ac0879c3SEdward Tomasz Napierala if ((n = malloc(sizeof(struct node))) == NULL) 744ac0879c3SEdward Tomasz Napierala err(1, NULL); 745ac0879c3SEdward Tomasz Napierala n->i = testdata[i]; 746ac0879c3SEdward Tomasz Napierala RB_INSERT(inttree, &head, n); 747ac0879c3SEdward Tomasz Napierala } 748ac0879c3SEdward Tomasz Napierala 749ac0879c3SEdward Tomasz Napierala RB_FOREACH(n, inttree, &head) { 750ac0879c3SEdward Tomasz Napierala printf("%d\en", n->i); 751ac0879c3SEdward Tomasz Napierala } 752ac0879c3SEdward Tomasz Napierala print_tree(RB_ROOT(&head)); 753*503b7f94SMaxim Konovalov printf("\enSum of values = %d\en", RB_ROOT(&head)->sum); 754ac0879c3SEdward Tomasz Napierala return (0); 755ac0879c3SEdward Tomasz Napierala} 756ac0879c3SEdward Tomasz Napierala.Ed 75787f5f0ecSDag-Erling Smørgrav.Sh NOTES 75887f5f0ecSDag-Erling SmørgravTrying to free a tree in the following way is a common error: 75987f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 76087f5f0ecSDag-Erling SmørgravSPLAY_FOREACH(var, NAME, head) { 76187f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 76287f5f0ecSDag-Erling Smørgrav free(var); 76387f5f0ecSDag-Erling Smørgrav} 76487f5f0ecSDag-Erling Smørgravfree(head); 76587f5f0ecSDag-Erling Smørgrav.Ed 76687f5f0ecSDag-Erling Smørgrav.Pp 76787f5f0ecSDag-Erling SmørgravSince 76887f5f0ecSDag-Erling Smørgrav.Va var 769480565d5SRuslan Ermilovis freed, the 77087f5f0ecSDag-Erling Smørgrav.Fn FOREACH 77187f5f0ecSDag-Erling Smørgravmacro refers to a pointer that may have been reallocated already. 77287f5f0ecSDag-Erling SmørgravProper code needs a second variable. 77387f5f0ecSDag-Erling Smørgrav.Bd -literal -offset indent 77487f5f0ecSDag-Erling Smørgravfor (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { 77587f5f0ecSDag-Erling Smørgrav nxt = SPLAY_NEXT(NAME, head, var); 77687f5f0ecSDag-Erling Smørgrav SPLAY_REMOVE(NAME, head, var); 77787f5f0ecSDag-Erling Smørgrav free(var); 77887f5f0ecSDag-Erling Smørgrav} 77987f5f0ecSDag-Erling Smørgrav.Ed 78087f5f0ecSDag-Erling Smørgrav.Pp 78187f5f0ecSDag-Erling SmørgravBoth 78287f5f0ecSDag-Erling Smørgrav.Fn RB_INSERT 78387f5f0ecSDag-Erling Smørgravand 78487f5f0ecSDag-Erling Smørgrav.Fn SPLAY_INSERT 78587f5f0ecSDag-Erling Smørgravreturn 786480565d5SRuslan Ermilov.Dv NULL 78787f5f0ecSDag-Erling Smørgravif the element was inserted in the tree successfully, otherwise they 78887f5f0ecSDag-Erling Smørgravreturn a pointer to the element with the colliding key. 78987f5f0ecSDag-Erling Smørgrav.Pp 79087f5f0ecSDag-Erling SmørgravAccordingly, 79187f5f0ecSDag-Erling Smørgrav.Fn RB_REMOVE 79287f5f0ecSDag-Erling Smørgravand 79387f5f0ecSDag-Erling Smørgrav.Fn SPLAY_REMOVE 79487f5f0ecSDag-Erling Smørgravreturn the pointer to the removed element otherwise they return 795480565d5SRuslan Ermilov.Dv NULL 79687f5f0ecSDag-Erling Smørgravto indicate an error. 797b9ec8f3bSSimon L. B. Nielsen.Sh SEE ALSO 798fad4b12bSEdward Tomasz Napierala.Xr arb 3 , 799b9ec8f3bSSimon L. B. Nielsen.Xr queue 3 800e605dcc9SDoug Moore.Rs 801e605dcc9SDoug Moore.%A "Bernhard Haeupler" 802e605dcc9SDoug Moore.%A "Siddhartha Sen" 803e605dcc9SDoug Moore.%A "Robert E. Tarjan" 804e605dcc9SDoug Moore.%T "Rank-Balanced Trees" 805e605dcc9SDoug Moore.%U "http://sidsen.azurewebsites.net/papers/rb-trees-talg.pdf" 806e605dcc9SDoug Moore.%J "ACM Transactions on Algorithms" 807e605dcc9SDoug Moore.%V "11" 808e605dcc9SDoug Moore.%N "4" 809e605dcc9SDoug Moore.%D "June 2015" 810e605dcc9SDoug Moore.Re 811757a04bfSSergio Carlavilla Delgado.Sh HISTORY 812757a04bfSSergio Carlavilla DelgadoThe tree macros first appeared in 813757a04bfSSergio Carlavilla Delgado.Fx 4.6 . 81487f5f0ecSDag-Erling Smørgrav.Sh AUTHORS 815480565d5SRuslan ErmilovThe author of the tree macros is 816480565d5SRuslan Ermilov.An Niels Provos . 817