1/* 2 * Copyright © 2017 Jason Ekstrand 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23#include "rb_tree.h" 24 25/** \file rb_tree.c 26 * 27 * An implementation of a red-black tree 28 * 29 * This file implements the guts of a red-black tree. The implementation 30 * is mostly based on the one in "Introduction to Algorithms", third 31 * edition, by Cormen, Leiserson, Rivest, and Stein. The primary 32 * divergence in our algorithms from those presented in CLRS is that we use 33 * NULL for the leaves instead of a sentinel. This means we have to do a 34 * tiny bit more tracking in our implementation of delete but it makes the 35 * algorithms far more explicit than stashing stuff in the sentinel. 36 */ 37 38#include <stdlib.h> 39#include <string.h> 40#include <assert.h> 41 42static bool 43rb_node_is_black(struct rb_node *n) 44{ 45 /* NULL nodes are leaves and therefore black */ 46 return (n == NULL) || (n->parent & 1); 47} 48 49static bool 50rb_node_is_red(struct rb_node *n) 51{ 52 return !rb_node_is_black(n); 53} 54 55static void 56rb_node_set_black(struct rb_node *n) 57{ 58 n->parent |= 1; 59} 60 61static void 62rb_node_set_red(struct rb_node *n) 63{ 64 n->parent &= ~1ull; 65} 66 67static void 68rb_node_copy_color(struct rb_node *dst, struct rb_node *src) 69{ 70 dst->parent = (dst->parent & ~1ull) | (src->parent & 1); 71} 72 73static void 74rb_node_set_parent(struct rb_node *n, struct rb_node *p) 75{ 76 n->parent = (n->parent & 1) | (uintptr_t)p; 77} 78 79static struct rb_node * 80rb_node_minimum(struct rb_node *node) 81{ 82 while (node->left) 83 node = node->left; 84 return node; 85} 86 87static struct rb_node * 88rb_node_maximum(struct rb_node *node) 89{ 90 while (node->right) 91 node = node->right; 92 return node; 93} 94 95void 96rb_tree_init(struct rb_tree *T) 97{ 98 T->root = NULL; 99} 100 101/** 102 * Replace the subtree of T rooted at u with the subtree rooted at v 103 * 104 * This is called RB-transplant in CLRS. 105 * 106 * The node to be replaced is assumed to be a non-leaf. 107 */ 108static void 109rb_tree_splice(struct rb_tree *T, struct rb_node *u, struct rb_node *v) 110{ 111 assert(u); 112 struct rb_node *p = rb_node_parent(u); 113 if (p == NULL) { 114 assert(T->root == u); 115 T->root = v; 116 } else if (u == p->left) { 117 p->left = v; 118 } else { 119 assert(u == p->right); 120 p->right = v; 121 } 122 if (v) 123 rb_node_set_parent(v, p); 124} 125 126static void 127rb_tree_rotate_left(struct rb_tree *T, struct rb_node *x) 128{ 129 assert(x && x->right); 130 131 struct rb_node *y = x->right; 132 x->right = y->left; 133 if (y->left) 134 rb_node_set_parent(y->left, x); 135 rb_tree_splice(T, x, y); 136 y->left = x; 137 rb_node_set_parent(x, y); 138} 139 140static void 141rb_tree_rotate_right(struct rb_tree *T, struct rb_node *y) 142{ 143 assert(y && y->left); 144 145 struct rb_node *x = y->left; 146 y->left = x->right; 147 if (x->right) 148 rb_node_set_parent(x->right, y); 149 rb_tree_splice(T, y, x); 150 x->right = y; 151 rb_node_set_parent(y, x); 152} 153 154void 155rb_tree_insert_at(struct rb_tree *T, struct rb_node *parent, 156 struct rb_node *node, bool insert_left) 157{ 158 /* This sets null children, parent, and a color of red */ 159 memset(node, 0, sizeof(*node)); 160 161 if (parent == NULL) { 162 assert(T->root == NULL); 163 T->root = node; 164 rb_node_set_black(node); 165 return; 166 } 167 168 if (insert_left) { 169 assert(parent->left == NULL); 170 parent->left = node; 171 } else { 172 assert(parent->right == NULL); 173 parent->right = node; 174 } 175 rb_node_set_parent(node, parent); 176 177 /* Now we do the insertion fixup */ 178 struct rb_node *z = node; 179 while (rb_node_is_red(rb_node_parent(z))) { 180 struct rb_node *z_p = rb_node_parent(z); 181 assert(z == z_p->left || z == z_p->right); 182 struct rb_node *z_p_p = rb_node_parent(z_p); 183 assert(z_p_p != NULL); 184 if (z_p == z_p_p->left) { 185 struct rb_node *y = z_p_p->right; 186 if (rb_node_is_red(y)) { 187 rb_node_set_black(z_p); 188 rb_node_set_black(y); 189 rb_node_set_red(z_p_p); 190 z = z_p_p; 191 } else { 192 if (z == z_p->right) { 193 z = z_p; 194 rb_tree_rotate_left(T, z); 195 /* We changed z */ 196 z_p = rb_node_parent(z); 197 assert(z == z_p->left || z == z_p->right); 198 z_p_p = rb_node_parent(z_p); 199 } 200 rb_node_set_black(z_p); 201 rb_node_set_red(z_p_p); 202 rb_tree_rotate_right(T, z_p_p); 203 } 204 } else { 205 struct rb_node *y = z_p_p->left; 206 if (rb_node_is_red(y)) { 207 rb_node_set_black(z_p); 208 rb_node_set_black(y); 209 rb_node_set_red(z_p_p); 210 z = z_p_p; 211 } else { 212 if (z == z_p->left) { 213 z = z_p; 214 rb_tree_rotate_right(T, z); 215 /* We changed z */ 216 z_p = rb_node_parent(z); 217 assert(z == z_p->left || z == z_p->right); 218 z_p_p = rb_node_parent(z_p); 219 } 220 rb_node_set_black(z_p); 221 rb_node_set_red(z_p_p); 222 rb_tree_rotate_left(T, z_p_p); 223 } 224 } 225 } 226 rb_node_set_black(T->root); 227} 228 229void 230rb_tree_remove(struct rb_tree *T, struct rb_node *z) 231{ 232 /* x_p is always the parent node of X. We have to track this 233 * separately because x may be NULL. 234 */ 235 struct rb_node *x, *x_p; 236 struct rb_node *y = z; 237 bool y_was_black = rb_node_is_black(y); 238 if (z->left == NULL) { 239 x = z->right; 240 x_p = rb_node_parent(z); 241 rb_tree_splice(T, z, x); 242 } else if (z->right == NULL) { 243 x = z->left; 244 x_p = rb_node_parent(z); 245 rb_tree_splice(T, z, x); 246 } else { 247 /* Find the minimum sub-node of z->right */ 248 y = rb_node_minimum(z->right); 249 y_was_black = rb_node_is_black(y); 250 251 x = y->right; 252 if (rb_node_parent(y) == z) { 253 x_p = y; 254 } else { 255 x_p = rb_node_parent(y); 256 rb_tree_splice(T, y, x); 257 y->right = z->right; 258 rb_node_set_parent(y->right, y); 259 } 260 assert(y->left == NULL); 261 rb_tree_splice(T, z, y); 262 y->left = z->left; 263 rb_node_set_parent(y->left, y); 264 rb_node_copy_color(y, z); 265 } 266 267 assert(x_p == NULL || x == x_p->left || x == x_p->right); 268 269 if (!y_was_black) 270 return; 271 272 /* Fixup RB tree after the delete */ 273 while (x != T->root && rb_node_is_black(x)) { 274 if (x == x_p->left) { 275 struct rb_node *w = x_p->right; 276 if (rb_node_is_red(w)) { 277 rb_node_set_black(w); 278 rb_node_set_red(x_p); 279 rb_tree_rotate_left(T, x_p); 280 assert(x == x_p->left); 281 w = x_p->right; 282 } 283 if (rb_node_is_black(w->left) && rb_node_is_black(w->right)) { 284 rb_node_set_red(w); 285 x = x_p; 286 } else { 287 if (rb_node_is_black(w->right)) { 288 rb_node_set_black(w->left); 289 rb_node_set_red(w); 290 rb_tree_rotate_right(T, w); 291 w = x_p->right; 292 } 293 rb_node_copy_color(w, x_p); 294 rb_node_set_black(x_p); 295 rb_node_set_black(w->right); 296 rb_tree_rotate_left(T, x_p); 297 x = T->root; 298 } 299 } else { 300 struct rb_node *w = x_p->left; 301 if (rb_node_is_red(w)) { 302 rb_node_set_black(w); 303 rb_node_set_red(x_p); 304 rb_tree_rotate_right(T, x_p); 305 assert(x == x_p->right); 306 w = x_p->left; 307 } 308 if (rb_node_is_black(w->right) && rb_node_is_black(w->left)) { 309 rb_node_set_red(w); 310 x = x_p; 311 } else { 312 if (rb_node_is_black(w->left)) { 313 rb_node_set_black(w->right); 314 rb_node_set_red(w); 315 rb_tree_rotate_left(T, w); 316 w = x_p->left; 317 } 318 rb_node_copy_color(w, x_p); 319 rb_node_set_black(x_p); 320 rb_node_set_black(w->left); 321 rb_tree_rotate_right(T, x_p); 322 x = T->root; 323 } 324 } 325 x_p = rb_node_parent(x); 326 } 327 if (x) 328 rb_node_set_black(x); 329} 330 331struct rb_node * 332rb_tree_first(struct rb_tree *T) 333{ 334 return T->root ? rb_node_minimum(T->root) : NULL; 335} 336 337struct rb_node * 338rb_tree_last(struct rb_tree *T) 339{ 340 return T->root ? rb_node_maximum(T->root) : NULL; 341} 342 343struct rb_node * 344rb_node_next(struct rb_node *node) 345{ 346 if (node->right) { 347 /* If we have a right child, then the next thing (compared to this 348 * node) is the left-most child of our right child. 349 */ 350 return rb_node_minimum(node->right); 351 } else { 352 /* If node doesn't have a right child, crawl back up the to the 353 * left until we hit a parent to the right. 354 */ 355 struct rb_node *p = rb_node_parent(node); 356 while (p && node == p->right) { 357 node = p; 358 p = rb_node_parent(node); 359 } 360 assert(p == NULL || node == p->left); 361 return p; 362 } 363} 364 365struct rb_node * 366rb_node_prev(struct rb_node *node) 367{ 368 if (node->left) { 369 /* If we have a left child, then the previous thing (compared to 370 * this node) is the right-most child of our left child. 371 */ 372 return rb_node_maximum(node->left); 373 } else { 374 /* If node doesn't have a left child, crawl back up the to the 375 * right until we hit a parent to the left. 376 */ 377 struct rb_node *p = rb_node_parent(node); 378 while (p && node == p->left) { 379 node = p; 380 p = rb_node_parent(node); 381 } 382 assert(p == NULL || node == p->right); 383 return p; 384 } 385} 386 387static void 388validate_rb_node(struct rb_node *n, int black_depth) 389{ 390 if (n == NULL) { 391 assert(black_depth == 0); 392 return; 393 } 394 395 if (rb_node_is_black(n)) { 396 black_depth--; 397 } else { 398 assert(rb_node_is_black(n->left)); 399 assert(rb_node_is_black(n->right)); 400 } 401 402 validate_rb_node(n->left, black_depth); 403 validate_rb_node(n->right, black_depth); 404} 405 406void 407rb_tree_validate(struct rb_tree *T) 408{ 409 if (T->root == NULL) 410 return; 411 412 assert(rb_node_is_black(T->root)); 413 414 unsigned black_depth = 0; 415 for (struct rb_node *n = T->root; n; n = n->left) { 416 if (rb_node_is_black(n)) 417 black_depth++; 418 } 419 420 validate_rb_node(T->root, black_depth); 421} 422