1*3f735377SArnaldo Carvalho de Melo /* 2*3f735377SArnaldo Carvalho de Melo Red Black Trees 3*3f735377SArnaldo Carvalho de Melo (C) 1999 Andrea Arcangeli <andrea@suse.de> 4*3f735377SArnaldo Carvalho de Melo (C) 2002 David Woodhouse <dwmw2@infradead.org> 5*3f735377SArnaldo Carvalho de Melo (C) 2012 Michel Lespinasse <walken@google.com> 6*3f735377SArnaldo Carvalho de Melo 7*3f735377SArnaldo Carvalho de Melo This program is free software; you can redistribute it and/or modify 8*3f735377SArnaldo Carvalho de Melo it under the terms of the GNU General Public License as published by 9*3f735377SArnaldo Carvalho de Melo the Free Software Foundation; either version 2 of the License, or 10*3f735377SArnaldo Carvalho de Melo (at your option) any later version. 11*3f735377SArnaldo Carvalho de Melo 12*3f735377SArnaldo Carvalho de Melo This program is distributed in the hope that it will be useful, 13*3f735377SArnaldo Carvalho de Melo but WITHOUT ANY WARRANTY; without even the implied warranty of 14*3f735377SArnaldo Carvalho de Melo MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*3f735377SArnaldo Carvalho de Melo GNU General Public License for more details. 16*3f735377SArnaldo Carvalho de Melo 17*3f735377SArnaldo Carvalho de Melo You should have received a copy of the GNU General Public License 18*3f735377SArnaldo Carvalho de Melo along with this program; if not, write to the Free Software 19*3f735377SArnaldo Carvalho de Melo Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20*3f735377SArnaldo Carvalho de Melo 21*3f735377SArnaldo Carvalho de Melo linux/lib/rbtree.c 22*3f735377SArnaldo Carvalho de Melo */ 23*3f735377SArnaldo Carvalho de Melo 24*3f735377SArnaldo Carvalho de Melo #include <linux/rbtree_augmented.h> 25*3f735377SArnaldo Carvalho de Melo 26*3f735377SArnaldo Carvalho de Melo /* 27*3f735377SArnaldo Carvalho de Melo * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree 28*3f735377SArnaldo Carvalho de Melo * 29*3f735377SArnaldo Carvalho de Melo * 1) A node is either red or black 30*3f735377SArnaldo Carvalho de Melo * 2) The root is black 31*3f735377SArnaldo Carvalho de Melo * 3) All leaves (NULL) are black 32*3f735377SArnaldo Carvalho de Melo * 4) Both children of every red node are black 33*3f735377SArnaldo Carvalho de Melo * 5) Every simple path from root to leaves contains the same number 34*3f735377SArnaldo Carvalho de Melo * of black nodes. 35*3f735377SArnaldo Carvalho de Melo * 36*3f735377SArnaldo Carvalho de Melo * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two 37*3f735377SArnaldo Carvalho de Melo * consecutive red nodes in a path and every red node is therefore followed by 38*3f735377SArnaldo Carvalho de Melo * a black. So if B is the number of black nodes on every simple path (as per 39*3f735377SArnaldo Carvalho de Melo * 5), then the longest possible path due to 4 is 2B. 40*3f735377SArnaldo Carvalho de Melo * 41*3f735377SArnaldo Carvalho de Melo * We shall indicate color with case, where black nodes are uppercase and red 42*3f735377SArnaldo Carvalho de Melo * nodes will be lowercase. Unknown color nodes shall be drawn as red within 43*3f735377SArnaldo Carvalho de Melo * parentheses and have some accompanying text comment. 44*3f735377SArnaldo Carvalho de Melo */ 45*3f735377SArnaldo Carvalho de Melo 46*3f735377SArnaldo Carvalho de Melo static inline void rb_set_black(struct rb_node *rb) 47*3f735377SArnaldo Carvalho de Melo { 48*3f735377SArnaldo Carvalho de Melo rb->__rb_parent_color |= RB_BLACK; 49*3f735377SArnaldo Carvalho de Melo } 50*3f735377SArnaldo Carvalho de Melo 51*3f735377SArnaldo Carvalho de Melo static inline struct rb_node *rb_red_parent(struct rb_node *red) 52*3f735377SArnaldo Carvalho de Melo { 53*3f735377SArnaldo Carvalho de Melo return (struct rb_node *)red->__rb_parent_color; 54*3f735377SArnaldo Carvalho de Melo } 55*3f735377SArnaldo Carvalho de Melo 56*3f735377SArnaldo Carvalho de Melo /* 57*3f735377SArnaldo Carvalho de Melo * Helper function for rotations: 58*3f735377SArnaldo Carvalho de Melo * - old's parent and color get assigned to new 59*3f735377SArnaldo Carvalho de Melo * - old gets assigned new as a parent and 'color' as a color. 60*3f735377SArnaldo Carvalho de Melo */ 61*3f735377SArnaldo Carvalho de Melo static inline void 62*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, 63*3f735377SArnaldo Carvalho de Melo struct rb_root *root, int color) 64*3f735377SArnaldo Carvalho de Melo { 65*3f735377SArnaldo Carvalho de Melo struct rb_node *parent = rb_parent(old); 66*3f735377SArnaldo Carvalho de Melo new->__rb_parent_color = old->__rb_parent_color; 67*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(old, new, color); 68*3f735377SArnaldo Carvalho de Melo __rb_change_child(old, new, parent, root); 69*3f735377SArnaldo Carvalho de Melo } 70*3f735377SArnaldo Carvalho de Melo 71*3f735377SArnaldo Carvalho de Melo static __always_inline void 72*3f735377SArnaldo Carvalho de Melo __rb_insert(struct rb_node *node, struct rb_root *root, 73*3f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 74*3f735377SArnaldo Carvalho de Melo { 75*3f735377SArnaldo Carvalho de Melo struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; 76*3f735377SArnaldo Carvalho de Melo 77*3f735377SArnaldo Carvalho de Melo while (true) { 78*3f735377SArnaldo Carvalho de Melo /* 79*3f735377SArnaldo Carvalho de Melo * Loop invariant: node is red 80*3f735377SArnaldo Carvalho de Melo * 81*3f735377SArnaldo Carvalho de Melo * If there is a black parent, we are done. 82*3f735377SArnaldo Carvalho de Melo * Otherwise, take some corrective action as we don't 83*3f735377SArnaldo Carvalho de Melo * want a red root or two consecutive red nodes. 84*3f735377SArnaldo Carvalho de Melo */ 85*3f735377SArnaldo Carvalho de Melo if (!parent) { 86*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(node, NULL, RB_BLACK); 87*3f735377SArnaldo Carvalho de Melo break; 88*3f735377SArnaldo Carvalho de Melo } else if (rb_is_black(parent)) 89*3f735377SArnaldo Carvalho de Melo break; 90*3f735377SArnaldo Carvalho de Melo 91*3f735377SArnaldo Carvalho de Melo gparent = rb_red_parent(parent); 92*3f735377SArnaldo Carvalho de Melo 93*3f735377SArnaldo Carvalho de Melo tmp = gparent->rb_right; 94*3f735377SArnaldo Carvalho de Melo if (parent != tmp) { /* parent == gparent->rb_left */ 95*3f735377SArnaldo Carvalho de Melo if (tmp && rb_is_red(tmp)) { 96*3f735377SArnaldo Carvalho de Melo /* 97*3f735377SArnaldo Carvalho de Melo * Case 1 - color flips 98*3f735377SArnaldo Carvalho de Melo * 99*3f735377SArnaldo Carvalho de Melo * G g 100*3f735377SArnaldo Carvalho de Melo * / \ / \ 101*3f735377SArnaldo Carvalho de Melo * p u --> P U 102*3f735377SArnaldo Carvalho de Melo * / / 103*3f735377SArnaldo Carvalho de Melo * n n 104*3f735377SArnaldo Carvalho de Melo * 105*3f735377SArnaldo Carvalho de Melo * However, since g's parent might be red, and 106*3f735377SArnaldo Carvalho de Melo * 4) does not allow this, we need to recurse 107*3f735377SArnaldo Carvalho de Melo * at g. 108*3f735377SArnaldo Carvalho de Melo */ 109*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 110*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, gparent, RB_BLACK); 111*3f735377SArnaldo Carvalho de Melo node = gparent; 112*3f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 113*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(node, parent, RB_RED); 114*3f735377SArnaldo Carvalho de Melo continue; 115*3f735377SArnaldo Carvalho de Melo } 116*3f735377SArnaldo Carvalho de Melo 117*3f735377SArnaldo Carvalho de Melo tmp = parent->rb_right; 118*3f735377SArnaldo Carvalho de Melo if (node == tmp) { 119*3f735377SArnaldo Carvalho de Melo /* 120*3f735377SArnaldo Carvalho de Melo * Case 2 - left rotate at parent 121*3f735377SArnaldo Carvalho de Melo * 122*3f735377SArnaldo Carvalho de Melo * G G 123*3f735377SArnaldo Carvalho de Melo * / \ / \ 124*3f735377SArnaldo Carvalho de Melo * p U --> n U 125*3f735377SArnaldo Carvalho de Melo * \ / 126*3f735377SArnaldo Carvalho de Melo * n p 127*3f735377SArnaldo Carvalho de Melo * 128*3f735377SArnaldo Carvalho de Melo * This still leaves us in violation of 4), the 129*3f735377SArnaldo Carvalho de Melo * continuation into Case 3 will fix that. 130*3f735377SArnaldo Carvalho de Melo */ 131*3f735377SArnaldo Carvalho de Melo parent->rb_right = tmp = node->rb_left; 132*3f735377SArnaldo Carvalho de Melo node->rb_left = parent; 133*3f735377SArnaldo Carvalho de Melo if (tmp) 134*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, parent, 135*3f735377SArnaldo Carvalho de Melo RB_BLACK); 136*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, node, RB_RED); 137*3f735377SArnaldo Carvalho de Melo augment_rotate(parent, node); 138*3f735377SArnaldo Carvalho de Melo parent = node; 139*3f735377SArnaldo Carvalho de Melo tmp = node->rb_right; 140*3f735377SArnaldo Carvalho de Melo } 141*3f735377SArnaldo Carvalho de Melo 142*3f735377SArnaldo Carvalho de Melo /* 143*3f735377SArnaldo Carvalho de Melo * Case 3 - right rotate at gparent 144*3f735377SArnaldo Carvalho de Melo * 145*3f735377SArnaldo Carvalho de Melo * G P 146*3f735377SArnaldo Carvalho de Melo * / \ / \ 147*3f735377SArnaldo Carvalho de Melo * p U --> n g 148*3f735377SArnaldo Carvalho de Melo * / \ 149*3f735377SArnaldo Carvalho de Melo * n U 150*3f735377SArnaldo Carvalho de Melo */ 151*3f735377SArnaldo Carvalho de Melo gparent->rb_left = tmp; /* == parent->rb_right */ 152*3f735377SArnaldo Carvalho de Melo parent->rb_right = gparent; 153*3f735377SArnaldo Carvalho de Melo if (tmp) 154*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 155*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(gparent, parent, root, RB_RED); 156*3f735377SArnaldo Carvalho de Melo augment_rotate(gparent, parent); 157*3f735377SArnaldo Carvalho de Melo break; 158*3f735377SArnaldo Carvalho de Melo } else { 159*3f735377SArnaldo Carvalho de Melo tmp = gparent->rb_left; 160*3f735377SArnaldo Carvalho de Melo if (tmp && rb_is_red(tmp)) { 161*3f735377SArnaldo Carvalho de Melo /* Case 1 - color flips */ 162*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 163*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, gparent, RB_BLACK); 164*3f735377SArnaldo Carvalho de Melo node = gparent; 165*3f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 166*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(node, parent, RB_RED); 167*3f735377SArnaldo Carvalho de Melo continue; 168*3f735377SArnaldo Carvalho de Melo } 169*3f735377SArnaldo Carvalho de Melo 170*3f735377SArnaldo Carvalho de Melo tmp = parent->rb_left; 171*3f735377SArnaldo Carvalho de Melo if (node == tmp) { 172*3f735377SArnaldo Carvalho de Melo /* Case 2 - right rotate at parent */ 173*3f735377SArnaldo Carvalho de Melo parent->rb_left = tmp = node->rb_right; 174*3f735377SArnaldo Carvalho de Melo node->rb_right = parent; 175*3f735377SArnaldo Carvalho de Melo if (tmp) 176*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, parent, 177*3f735377SArnaldo Carvalho de Melo RB_BLACK); 178*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, node, RB_RED); 179*3f735377SArnaldo Carvalho de Melo augment_rotate(parent, node); 180*3f735377SArnaldo Carvalho de Melo parent = node; 181*3f735377SArnaldo Carvalho de Melo tmp = node->rb_left; 182*3f735377SArnaldo Carvalho de Melo } 183*3f735377SArnaldo Carvalho de Melo 184*3f735377SArnaldo Carvalho de Melo /* Case 3 - left rotate at gparent */ 185*3f735377SArnaldo Carvalho de Melo gparent->rb_right = tmp; /* == parent->rb_left */ 186*3f735377SArnaldo Carvalho de Melo parent->rb_left = gparent; 187*3f735377SArnaldo Carvalho de Melo if (tmp) 188*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 189*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(gparent, parent, root, RB_RED); 190*3f735377SArnaldo Carvalho de Melo augment_rotate(gparent, parent); 191*3f735377SArnaldo Carvalho de Melo break; 192*3f735377SArnaldo Carvalho de Melo } 193*3f735377SArnaldo Carvalho de Melo } 194*3f735377SArnaldo Carvalho de Melo } 195*3f735377SArnaldo Carvalho de Melo 196*3f735377SArnaldo Carvalho de Melo /* 197*3f735377SArnaldo Carvalho de Melo * Inline version for rb_erase() use - we want to be able to inline 198*3f735377SArnaldo Carvalho de Melo * and eliminate the dummy_rotate callback there 199*3f735377SArnaldo Carvalho de Melo */ 200*3f735377SArnaldo Carvalho de Melo static __always_inline void 201*3f735377SArnaldo Carvalho de Melo ____rb_erase_color(struct rb_node *parent, struct rb_root *root, 202*3f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 203*3f735377SArnaldo Carvalho de Melo { 204*3f735377SArnaldo Carvalho de Melo struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; 205*3f735377SArnaldo Carvalho de Melo 206*3f735377SArnaldo Carvalho de Melo while (true) { 207*3f735377SArnaldo Carvalho de Melo /* 208*3f735377SArnaldo Carvalho de Melo * Loop invariants: 209*3f735377SArnaldo Carvalho de Melo * - node is black (or NULL on first iteration) 210*3f735377SArnaldo Carvalho de Melo * - node is not the root (parent is not NULL) 211*3f735377SArnaldo Carvalho de Melo * - All leaf paths going through parent and node have a 212*3f735377SArnaldo Carvalho de Melo * black node count that is 1 lower than other leaf paths. 213*3f735377SArnaldo Carvalho de Melo */ 214*3f735377SArnaldo Carvalho de Melo sibling = parent->rb_right; 215*3f735377SArnaldo Carvalho de Melo if (node != sibling) { /* node == parent->rb_left */ 216*3f735377SArnaldo Carvalho de Melo if (rb_is_red(sibling)) { 217*3f735377SArnaldo Carvalho de Melo /* 218*3f735377SArnaldo Carvalho de Melo * Case 1 - left rotate at parent 219*3f735377SArnaldo Carvalho de Melo * 220*3f735377SArnaldo Carvalho de Melo * P S 221*3f735377SArnaldo Carvalho de Melo * / \ / \ 222*3f735377SArnaldo Carvalho de Melo * N s --> p Sr 223*3f735377SArnaldo Carvalho de Melo * / \ / \ 224*3f735377SArnaldo Carvalho de Melo * Sl Sr N Sl 225*3f735377SArnaldo Carvalho de Melo */ 226*3f735377SArnaldo Carvalho de Melo parent->rb_right = tmp1 = sibling->rb_left; 227*3f735377SArnaldo Carvalho de Melo sibling->rb_left = parent; 228*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, parent, RB_BLACK); 229*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 230*3f735377SArnaldo Carvalho de Melo RB_RED); 231*3f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 232*3f735377SArnaldo Carvalho de Melo sibling = tmp1; 233*3f735377SArnaldo Carvalho de Melo } 234*3f735377SArnaldo Carvalho de Melo tmp1 = sibling->rb_right; 235*3f735377SArnaldo Carvalho de Melo if (!tmp1 || rb_is_black(tmp1)) { 236*3f735377SArnaldo Carvalho de Melo tmp2 = sibling->rb_left; 237*3f735377SArnaldo Carvalho de Melo if (!tmp2 || rb_is_black(tmp2)) { 238*3f735377SArnaldo Carvalho de Melo /* 239*3f735377SArnaldo Carvalho de Melo * Case 2 - sibling color flip 240*3f735377SArnaldo Carvalho de Melo * (p could be either color here) 241*3f735377SArnaldo Carvalho de Melo * 242*3f735377SArnaldo Carvalho de Melo * (p) (p) 243*3f735377SArnaldo Carvalho de Melo * / \ / \ 244*3f735377SArnaldo Carvalho de Melo * N S --> N s 245*3f735377SArnaldo Carvalho de Melo * / \ / \ 246*3f735377SArnaldo Carvalho de Melo * Sl Sr Sl Sr 247*3f735377SArnaldo Carvalho de Melo * 248*3f735377SArnaldo Carvalho de Melo * This leaves us violating 5) which 249*3f735377SArnaldo Carvalho de Melo * can be fixed by flipping p to black 250*3f735377SArnaldo Carvalho de Melo * if it was red, or by recursing at p. 251*3f735377SArnaldo Carvalho de Melo * p is red when coming from Case 1. 252*3f735377SArnaldo Carvalho de Melo */ 253*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(sibling, parent, 254*3f735377SArnaldo Carvalho de Melo RB_RED); 255*3f735377SArnaldo Carvalho de Melo if (rb_is_red(parent)) 256*3f735377SArnaldo Carvalho de Melo rb_set_black(parent); 257*3f735377SArnaldo Carvalho de Melo else { 258*3f735377SArnaldo Carvalho de Melo node = parent; 259*3f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 260*3f735377SArnaldo Carvalho de Melo if (parent) 261*3f735377SArnaldo Carvalho de Melo continue; 262*3f735377SArnaldo Carvalho de Melo } 263*3f735377SArnaldo Carvalho de Melo break; 264*3f735377SArnaldo Carvalho de Melo } 265*3f735377SArnaldo Carvalho de Melo /* 266*3f735377SArnaldo Carvalho de Melo * Case 3 - right rotate at sibling 267*3f735377SArnaldo Carvalho de Melo * (p could be either color here) 268*3f735377SArnaldo Carvalho de Melo * 269*3f735377SArnaldo Carvalho de Melo * (p) (p) 270*3f735377SArnaldo Carvalho de Melo * / \ / \ 271*3f735377SArnaldo Carvalho de Melo * N S --> N Sl 272*3f735377SArnaldo Carvalho de Melo * / \ \ 273*3f735377SArnaldo Carvalho de Melo * sl Sr s 274*3f735377SArnaldo Carvalho de Melo * \ 275*3f735377SArnaldo Carvalho de Melo * Sr 276*3f735377SArnaldo Carvalho de Melo */ 277*3f735377SArnaldo Carvalho de Melo sibling->rb_left = tmp1 = tmp2->rb_right; 278*3f735377SArnaldo Carvalho de Melo tmp2->rb_right = sibling; 279*3f735377SArnaldo Carvalho de Melo parent->rb_right = tmp2; 280*3f735377SArnaldo Carvalho de Melo if (tmp1) 281*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, 282*3f735377SArnaldo Carvalho de Melo RB_BLACK); 283*3f735377SArnaldo Carvalho de Melo augment_rotate(sibling, tmp2); 284*3f735377SArnaldo Carvalho de Melo tmp1 = sibling; 285*3f735377SArnaldo Carvalho de Melo sibling = tmp2; 286*3f735377SArnaldo Carvalho de Melo } 287*3f735377SArnaldo Carvalho de Melo /* 288*3f735377SArnaldo Carvalho de Melo * Case 4 - left rotate at parent + color flips 289*3f735377SArnaldo Carvalho de Melo * (p and sl could be either color here. 290*3f735377SArnaldo Carvalho de Melo * After rotation, p becomes black, s acquires 291*3f735377SArnaldo Carvalho de Melo * p's color, and sl keeps its color) 292*3f735377SArnaldo Carvalho de Melo * 293*3f735377SArnaldo Carvalho de Melo * (p) (s) 294*3f735377SArnaldo Carvalho de Melo * / \ / \ 295*3f735377SArnaldo Carvalho de Melo * N S --> P Sr 296*3f735377SArnaldo Carvalho de Melo * / \ / \ 297*3f735377SArnaldo Carvalho de Melo * (sl) sr N (sl) 298*3f735377SArnaldo Carvalho de Melo */ 299*3f735377SArnaldo Carvalho de Melo parent->rb_right = tmp2 = sibling->rb_left; 300*3f735377SArnaldo Carvalho de Melo sibling->rb_left = parent; 301*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, RB_BLACK); 302*3f735377SArnaldo Carvalho de Melo if (tmp2) 303*3f735377SArnaldo Carvalho de Melo rb_set_parent(tmp2, parent); 304*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 305*3f735377SArnaldo Carvalho de Melo RB_BLACK); 306*3f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 307*3f735377SArnaldo Carvalho de Melo break; 308*3f735377SArnaldo Carvalho de Melo } else { 309*3f735377SArnaldo Carvalho de Melo sibling = parent->rb_left; 310*3f735377SArnaldo Carvalho de Melo if (rb_is_red(sibling)) { 311*3f735377SArnaldo Carvalho de Melo /* Case 1 - right rotate at parent */ 312*3f735377SArnaldo Carvalho de Melo parent->rb_left = tmp1 = sibling->rb_right; 313*3f735377SArnaldo Carvalho de Melo sibling->rb_right = parent; 314*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, parent, RB_BLACK); 315*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 316*3f735377SArnaldo Carvalho de Melo RB_RED); 317*3f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 318*3f735377SArnaldo Carvalho de Melo sibling = tmp1; 319*3f735377SArnaldo Carvalho de Melo } 320*3f735377SArnaldo Carvalho de Melo tmp1 = sibling->rb_left; 321*3f735377SArnaldo Carvalho de Melo if (!tmp1 || rb_is_black(tmp1)) { 322*3f735377SArnaldo Carvalho de Melo tmp2 = sibling->rb_right; 323*3f735377SArnaldo Carvalho de Melo if (!tmp2 || rb_is_black(tmp2)) { 324*3f735377SArnaldo Carvalho de Melo /* Case 2 - sibling color flip */ 325*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(sibling, parent, 326*3f735377SArnaldo Carvalho de Melo RB_RED); 327*3f735377SArnaldo Carvalho de Melo if (rb_is_red(parent)) 328*3f735377SArnaldo Carvalho de Melo rb_set_black(parent); 329*3f735377SArnaldo Carvalho de Melo else { 330*3f735377SArnaldo Carvalho de Melo node = parent; 331*3f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 332*3f735377SArnaldo Carvalho de Melo if (parent) 333*3f735377SArnaldo Carvalho de Melo continue; 334*3f735377SArnaldo Carvalho de Melo } 335*3f735377SArnaldo Carvalho de Melo break; 336*3f735377SArnaldo Carvalho de Melo } 337*3f735377SArnaldo Carvalho de Melo /* Case 3 - right rotate at sibling */ 338*3f735377SArnaldo Carvalho de Melo sibling->rb_right = tmp1 = tmp2->rb_left; 339*3f735377SArnaldo Carvalho de Melo tmp2->rb_left = sibling; 340*3f735377SArnaldo Carvalho de Melo parent->rb_left = tmp2; 341*3f735377SArnaldo Carvalho de Melo if (tmp1) 342*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, 343*3f735377SArnaldo Carvalho de Melo RB_BLACK); 344*3f735377SArnaldo Carvalho de Melo augment_rotate(sibling, tmp2); 345*3f735377SArnaldo Carvalho de Melo tmp1 = sibling; 346*3f735377SArnaldo Carvalho de Melo sibling = tmp2; 347*3f735377SArnaldo Carvalho de Melo } 348*3f735377SArnaldo Carvalho de Melo /* Case 4 - left rotate at parent + color flips */ 349*3f735377SArnaldo Carvalho de Melo parent->rb_left = tmp2 = sibling->rb_right; 350*3f735377SArnaldo Carvalho de Melo sibling->rb_right = parent; 351*3f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, RB_BLACK); 352*3f735377SArnaldo Carvalho de Melo if (tmp2) 353*3f735377SArnaldo Carvalho de Melo rb_set_parent(tmp2, parent); 354*3f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 355*3f735377SArnaldo Carvalho de Melo RB_BLACK); 356*3f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 357*3f735377SArnaldo Carvalho de Melo break; 358*3f735377SArnaldo Carvalho de Melo } 359*3f735377SArnaldo Carvalho de Melo } 360*3f735377SArnaldo Carvalho de Melo } 361*3f735377SArnaldo Carvalho de Melo 362*3f735377SArnaldo Carvalho de Melo /* Non-inline version for rb_erase_augmented() use */ 363*3f735377SArnaldo Carvalho de Melo void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 364*3f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 365*3f735377SArnaldo Carvalho de Melo { 366*3f735377SArnaldo Carvalho de Melo ____rb_erase_color(parent, root, augment_rotate); 367*3f735377SArnaldo Carvalho de Melo } 368*3f735377SArnaldo Carvalho de Melo 369*3f735377SArnaldo Carvalho de Melo /* 370*3f735377SArnaldo Carvalho de Melo * Non-augmented rbtree manipulation functions. 371*3f735377SArnaldo Carvalho de Melo * 372*3f735377SArnaldo Carvalho de Melo * We use dummy augmented callbacks here, and have the compiler optimize them 373*3f735377SArnaldo Carvalho de Melo * out of the rb_insert_color() and rb_erase() function definitions. 374*3f735377SArnaldo Carvalho de Melo */ 375*3f735377SArnaldo Carvalho de Melo 376*3f735377SArnaldo Carvalho de Melo static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} 377*3f735377SArnaldo Carvalho de Melo static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} 378*3f735377SArnaldo Carvalho de Melo static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} 379*3f735377SArnaldo Carvalho de Melo 380*3f735377SArnaldo Carvalho de Melo static const struct rb_augment_callbacks dummy_callbacks = { 381*3f735377SArnaldo Carvalho de Melo dummy_propagate, dummy_copy, dummy_rotate 382*3f735377SArnaldo Carvalho de Melo }; 383*3f735377SArnaldo Carvalho de Melo 384*3f735377SArnaldo Carvalho de Melo void rb_insert_color(struct rb_node *node, struct rb_root *root) 385*3f735377SArnaldo Carvalho de Melo { 386*3f735377SArnaldo Carvalho de Melo __rb_insert(node, root, dummy_rotate); 387*3f735377SArnaldo Carvalho de Melo } 388*3f735377SArnaldo Carvalho de Melo 389*3f735377SArnaldo Carvalho de Melo void rb_erase(struct rb_node *node, struct rb_root *root) 390*3f735377SArnaldo Carvalho de Melo { 391*3f735377SArnaldo Carvalho de Melo struct rb_node *rebalance; 392*3f735377SArnaldo Carvalho de Melo rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); 393*3f735377SArnaldo Carvalho de Melo if (rebalance) 394*3f735377SArnaldo Carvalho de Melo ____rb_erase_color(rebalance, root, dummy_rotate); 395*3f735377SArnaldo Carvalho de Melo } 396*3f735377SArnaldo Carvalho de Melo 397*3f735377SArnaldo Carvalho de Melo /* 398*3f735377SArnaldo Carvalho de Melo * Augmented rbtree manipulation functions. 399*3f735377SArnaldo Carvalho de Melo * 400*3f735377SArnaldo Carvalho de Melo * This instantiates the same __always_inline functions as in the non-augmented 401*3f735377SArnaldo Carvalho de Melo * case, but this time with user-defined callbacks. 402*3f735377SArnaldo Carvalho de Melo */ 403*3f735377SArnaldo Carvalho de Melo 404*3f735377SArnaldo Carvalho de Melo void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 405*3f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 406*3f735377SArnaldo Carvalho de Melo { 407*3f735377SArnaldo Carvalho de Melo __rb_insert(node, root, augment_rotate); 408*3f735377SArnaldo Carvalho de Melo } 409*3f735377SArnaldo Carvalho de Melo 410*3f735377SArnaldo Carvalho de Melo /* 411*3f735377SArnaldo Carvalho de Melo * This function returns the first node (in sort order) of the tree. 412*3f735377SArnaldo Carvalho de Melo */ 413*3f735377SArnaldo Carvalho de Melo struct rb_node *rb_first(const struct rb_root *root) 414*3f735377SArnaldo Carvalho de Melo { 415*3f735377SArnaldo Carvalho de Melo struct rb_node *n; 416*3f735377SArnaldo Carvalho de Melo 417*3f735377SArnaldo Carvalho de Melo n = root->rb_node; 418*3f735377SArnaldo Carvalho de Melo if (!n) 419*3f735377SArnaldo Carvalho de Melo return NULL; 420*3f735377SArnaldo Carvalho de Melo while (n->rb_left) 421*3f735377SArnaldo Carvalho de Melo n = n->rb_left; 422*3f735377SArnaldo Carvalho de Melo return n; 423*3f735377SArnaldo Carvalho de Melo } 424*3f735377SArnaldo Carvalho de Melo 425*3f735377SArnaldo Carvalho de Melo struct rb_node *rb_last(const struct rb_root *root) 426*3f735377SArnaldo Carvalho de Melo { 427*3f735377SArnaldo Carvalho de Melo struct rb_node *n; 428*3f735377SArnaldo Carvalho de Melo 429*3f735377SArnaldo Carvalho de Melo n = root->rb_node; 430*3f735377SArnaldo Carvalho de Melo if (!n) 431*3f735377SArnaldo Carvalho de Melo return NULL; 432*3f735377SArnaldo Carvalho de Melo while (n->rb_right) 433*3f735377SArnaldo Carvalho de Melo n = n->rb_right; 434*3f735377SArnaldo Carvalho de Melo return n; 435*3f735377SArnaldo Carvalho de Melo } 436*3f735377SArnaldo Carvalho de Melo 437*3f735377SArnaldo Carvalho de Melo struct rb_node *rb_next(const struct rb_node *node) 438*3f735377SArnaldo Carvalho de Melo { 439*3f735377SArnaldo Carvalho de Melo struct rb_node *parent; 440*3f735377SArnaldo Carvalho de Melo 441*3f735377SArnaldo Carvalho de Melo if (RB_EMPTY_NODE(node)) 442*3f735377SArnaldo Carvalho de Melo return NULL; 443*3f735377SArnaldo Carvalho de Melo 444*3f735377SArnaldo Carvalho de Melo /* 445*3f735377SArnaldo Carvalho de Melo * If we have a right-hand child, go down and then left as far 446*3f735377SArnaldo Carvalho de Melo * as we can. 447*3f735377SArnaldo Carvalho de Melo */ 448*3f735377SArnaldo Carvalho de Melo if (node->rb_right) { 449*3f735377SArnaldo Carvalho de Melo node = node->rb_right; 450*3f735377SArnaldo Carvalho de Melo while (node->rb_left) 451*3f735377SArnaldo Carvalho de Melo node=node->rb_left; 452*3f735377SArnaldo Carvalho de Melo return (struct rb_node *)node; 453*3f735377SArnaldo Carvalho de Melo } 454*3f735377SArnaldo Carvalho de Melo 455*3f735377SArnaldo Carvalho de Melo /* 456*3f735377SArnaldo Carvalho de Melo * No right-hand children. Everything down and left is smaller than us, 457*3f735377SArnaldo Carvalho de Melo * so any 'next' node must be in the general direction of our parent. 458*3f735377SArnaldo Carvalho de Melo * Go up the tree; any time the ancestor is a right-hand child of its 459*3f735377SArnaldo Carvalho de Melo * parent, keep going up. First time it's a left-hand child of its 460*3f735377SArnaldo Carvalho de Melo * parent, said parent is our 'next' node. 461*3f735377SArnaldo Carvalho de Melo */ 462*3f735377SArnaldo Carvalho de Melo while ((parent = rb_parent(node)) && node == parent->rb_right) 463*3f735377SArnaldo Carvalho de Melo node = parent; 464*3f735377SArnaldo Carvalho de Melo 465*3f735377SArnaldo Carvalho de Melo return parent; 466*3f735377SArnaldo Carvalho de Melo } 467*3f735377SArnaldo Carvalho de Melo 468*3f735377SArnaldo Carvalho de Melo struct rb_node *rb_prev(const struct rb_node *node) 469*3f735377SArnaldo Carvalho de Melo { 470*3f735377SArnaldo Carvalho de Melo struct rb_node *parent; 471*3f735377SArnaldo Carvalho de Melo 472*3f735377SArnaldo Carvalho de Melo if (RB_EMPTY_NODE(node)) 473*3f735377SArnaldo Carvalho de Melo return NULL; 474*3f735377SArnaldo Carvalho de Melo 475*3f735377SArnaldo Carvalho de Melo /* 476*3f735377SArnaldo Carvalho de Melo * If we have a left-hand child, go down and then right as far 477*3f735377SArnaldo Carvalho de Melo * as we can. 478*3f735377SArnaldo Carvalho de Melo */ 479*3f735377SArnaldo Carvalho de Melo if (node->rb_left) { 480*3f735377SArnaldo Carvalho de Melo node = node->rb_left; 481*3f735377SArnaldo Carvalho de Melo while (node->rb_right) 482*3f735377SArnaldo Carvalho de Melo node=node->rb_right; 483*3f735377SArnaldo Carvalho de Melo return (struct rb_node *)node; 484*3f735377SArnaldo Carvalho de Melo } 485*3f735377SArnaldo Carvalho de Melo 486*3f735377SArnaldo Carvalho de Melo /* 487*3f735377SArnaldo Carvalho de Melo * No left-hand children. Go up till we find an ancestor which 488*3f735377SArnaldo Carvalho de Melo * is a right-hand child of its parent. 489*3f735377SArnaldo Carvalho de Melo */ 490*3f735377SArnaldo Carvalho de Melo while ((parent = rb_parent(node)) && node == parent->rb_left) 491*3f735377SArnaldo Carvalho de Melo node = parent; 492*3f735377SArnaldo Carvalho de Melo 493*3f735377SArnaldo Carvalho de Melo return parent; 494*3f735377SArnaldo Carvalho de Melo } 495*3f735377SArnaldo Carvalho de Melo 496*3f735377SArnaldo Carvalho de Melo void rb_replace_node(struct rb_node *victim, struct rb_node *new, 497*3f735377SArnaldo Carvalho de Melo struct rb_root *root) 498*3f735377SArnaldo Carvalho de Melo { 499*3f735377SArnaldo Carvalho de Melo struct rb_node *parent = rb_parent(victim); 500*3f735377SArnaldo Carvalho de Melo 501*3f735377SArnaldo Carvalho de Melo /* Set the surrounding nodes to point to the replacement */ 502*3f735377SArnaldo Carvalho de Melo __rb_change_child(victim, new, parent, root); 503*3f735377SArnaldo Carvalho de Melo if (victim->rb_left) 504*3f735377SArnaldo Carvalho de Melo rb_set_parent(victim->rb_left, new); 505*3f735377SArnaldo Carvalho de Melo if (victim->rb_right) 506*3f735377SArnaldo Carvalho de Melo rb_set_parent(victim->rb_right, new); 507*3f735377SArnaldo Carvalho de Melo 508*3f735377SArnaldo Carvalho de Melo /* Copy the pointers/colour from the victim to the replacement */ 509*3f735377SArnaldo Carvalho de Melo *new = *victim; 510*3f735377SArnaldo Carvalho de Melo } 511*3f735377SArnaldo Carvalho de Melo 512*3f735377SArnaldo Carvalho de Melo static struct rb_node *rb_left_deepest_node(const struct rb_node *node) 513*3f735377SArnaldo Carvalho de Melo { 514*3f735377SArnaldo Carvalho de Melo for (;;) { 515*3f735377SArnaldo Carvalho de Melo if (node->rb_left) 516*3f735377SArnaldo Carvalho de Melo node = node->rb_left; 517*3f735377SArnaldo Carvalho de Melo else if (node->rb_right) 518*3f735377SArnaldo Carvalho de Melo node = node->rb_right; 519*3f735377SArnaldo Carvalho de Melo else 520*3f735377SArnaldo Carvalho de Melo return (struct rb_node *)node; 521*3f735377SArnaldo Carvalho de Melo } 522*3f735377SArnaldo Carvalho de Melo } 523*3f735377SArnaldo Carvalho de Melo 524*3f735377SArnaldo Carvalho de Melo struct rb_node *rb_next_postorder(const struct rb_node *node) 525*3f735377SArnaldo Carvalho de Melo { 526*3f735377SArnaldo Carvalho de Melo const struct rb_node *parent; 527*3f735377SArnaldo Carvalho de Melo if (!node) 528*3f735377SArnaldo Carvalho de Melo return NULL; 529*3f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 530*3f735377SArnaldo Carvalho de Melo 531*3f735377SArnaldo Carvalho de Melo /* If we're sitting on node, we've already seen our children */ 532*3f735377SArnaldo Carvalho de Melo if (parent && node == parent->rb_left && parent->rb_right) { 533*3f735377SArnaldo Carvalho de Melo /* If we are the parent's left node, go to the parent's right 534*3f735377SArnaldo Carvalho de Melo * node then all the way down to the left */ 535*3f735377SArnaldo Carvalho de Melo return rb_left_deepest_node(parent->rb_right); 536*3f735377SArnaldo Carvalho de Melo } else 537*3f735377SArnaldo Carvalho de Melo /* Otherwise we are the parent's right node, and the parent 538*3f735377SArnaldo Carvalho de Melo * should be next */ 539*3f735377SArnaldo Carvalho de Melo return (struct rb_node *)parent; 540*3f735377SArnaldo Carvalho de Melo } 541*3f735377SArnaldo Carvalho de Melo 542*3f735377SArnaldo Carvalho de Melo struct rb_node *rb_first_postorder(const struct rb_root *root) 543*3f735377SArnaldo Carvalho de Melo { 544*3f735377SArnaldo Carvalho de Melo if (!root->rb_node) 545*3f735377SArnaldo Carvalho de Melo return NULL; 546*3f735377SArnaldo Carvalho de Melo 547*3f735377SArnaldo Carvalho de Melo return rb_left_deepest_node(root->rb_node); 548*3f735377SArnaldo Carvalho de Melo } 549