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