2 * Copyright (c) 2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009).
18 * Introduction to algorithms. MIT press, 3rd Edition, Ch. 13
21 #include <vppinfra/rbtree.h>
23 static inline rb_node_t *
24 rb_node_right (rb_tree_t * rt, rb_node_t * n)
26 return pool_elt_at_index (rt->nodes, n->right);
29 static inline rb_node_t *
30 rb_node_left (rb_tree_t * rt, rb_node_t * n)
32 return pool_elt_at_index (rt->nodes, n->left);
35 static inline rb_node_t *
36 rb_node_parent (rb_tree_t * rt, rb_node_t * n)
38 return pool_elt_at_index (rt->nodes, n->parent);
42 rb_tree_rotate_left (rb_tree_t * rt, rb_node_t * x)
44 rb_node_t *y, *tmp, *xp;
45 rb_node_index_t xi, yi;
47 xi = rb_node_index (rt, x);
49 y = rb_node_right (rt, x);
51 if (y->left != RBTREE_TNIL_INDEX)
53 tmp = rb_node_left (rt, y);
56 xp = rb_node_parent (rt, x);
57 y->parent = x->parent;
58 if (x->parent == RBTREE_TNIL_INDEX)
59 rt->root = rb_node_index (rt, y);
60 else if (xp->left == xi)
69 rb_tree_rotate_right (rb_tree_t * rt, rb_node_t * y)
71 rb_node_index_t yi, xi;
74 yi = rb_node_index (rt, y);
76 x = rb_node_left (rt, y);
78 if (x->right != RBTREE_TNIL_INDEX)
80 rb_node_t *tmp = rb_node_right (rt, x);
83 yp = rb_node_parent (rt, y);
84 x->parent = y->parent;
85 if (y->parent == RBTREE_TNIL_INDEX)
86 rt->root = rb_node_index (rt, x);
87 else if (yp->right == yi)
96 rb_tree_insert (rb_tree_t * rt, rb_node_t * z)
98 rb_node_index_t yi = 0, xi = rt->root, zi;
99 rb_node_t *y, *zpp, *x, *zp;
101 y = rb_node (rt, RBTREE_TNIL_INDEX);
102 while (xi != RBTREE_TNIL_INDEX)
104 x = rb_node (rt, xi);
111 yi = rb_node_index (rt, y);
113 if (yi == RBTREE_TNIL_INDEX)
114 rt->root = rb_node_index (rt, z);
115 else if (z->key < y->key)
116 y->left = rb_node_index (rt, z);
118 y->right = rb_node_index (rt, z);
120 /* Tree fixup stage */
121 while (y->color == RBTREE_RED)
123 zi = rb_node_index (rt, z);
124 zp = rb_node_parent (rt, z);
125 zpp = rb_node_parent (rt, zp);
126 if (z->parent == zpp->left)
128 y = rb_node_right (rt, zpp);
129 if (y->color == RBTREE_RED)
131 zp->color = RBTREE_BLACK;
132 y->color = RBTREE_BLACK;
133 zpp->color = RBTREE_RED;
141 rb_tree_rotate_left (rt, z);
142 zp = rb_node (rt, z->parent);
143 zpp = rb_node (rt, zp->parent);
145 zp->color = RBTREE_BLACK;
146 zpp->color = RBTREE_RED;
147 rb_tree_rotate_right (rt, zpp);
152 y = rb_node (rt, zpp->left);
153 if (y->color == RBTREE_RED)
155 zp->color = RBTREE_BLACK;
156 y->color = RBTREE_BLACK;
157 zpp->color = RBTREE_RED;
165 rb_tree_rotate_right (rt, z);
166 zp = rb_node (rt, z->parent);
167 zpp = rb_node (rt, zp->parent);
169 zp->color = RBTREE_BLACK;
170 zpp->color = RBTREE_RED;
171 rb_tree_rotate_left (rt, zpp);
175 rb_node (rt, rt->root)->color = RBTREE_BLACK;
179 rb_tree_add (rb_tree_t * rt, u32 key)
183 pool_get_zero (rt->nodes, n);
185 n->color = RBTREE_RED;
186 rb_tree_insert (rt, n);
187 return rb_node_index (rt, n);
191 rb_tree_add2 (rb_tree_t * rt, u32 key, u32 opaque)
195 pool_get_zero (rt->nodes, n);
197 n->color = RBTREE_RED;
199 rb_tree_insert (rt, n);
200 return rb_node_index (rt, n);
204 rb_tree_search_subtree (rb_tree_t * rt, rb_node_t * x, u32 key)
206 while (rb_node_index (rt, x) != RBTREE_TNIL_INDEX && key != x->key)
208 x = rb_node_left (rt, x);
210 x = rb_node_right (rt, x);
215 rb_tree_min_subtree (rb_tree_t * rt, rb_node_t * x)
217 while (x->left != RBTREE_TNIL_INDEX)
218 x = rb_node_left (rt, x);
223 rb_tree_max_subtree (rb_tree_t * rt, rb_node_t * x)
225 while (x->right != RBTREE_TNIL_INDEX)
226 x = rb_node_right (rt, x);
231 rb_tree_successor (rb_tree_t * rt, rb_node_t * x)
235 if (x->right != RBTREE_TNIL_INDEX)
236 return rb_tree_min_subtree (rt, rb_node_right (rt, x));
238 y = rb_node_parent (rt, x);
239 while (!rb_node_is_tnil (rt, y) && y->right == rb_node_index (rt, x))
242 y = rb_node_parent (rt, y);
248 rb_tree_predecessor (rb_tree_t * rt, rb_node_t * x)
252 if (x->left != RBTREE_TNIL_INDEX)
253 return rb_tree_max_subtree (rt, rb_node_left (rt, x));
255 y = rb_node_parent (rt, x);
256 while (!rb_node_is_tnil (rt, y) && y->left == rb_node_index (rt, x))
259 y = rb_node_parent (rt, y);
265 rb_tree_transplant (rb_tree_t * rt, rb_node_t * u, rb_node_t * v)
269 up = rb_node_parent (rt, u);
270 if (u->parent == RBTREE_TNIL_INDEX)
271 rt->root = rb_node_index (rt, v);
272 else if (rb_node_index (rt, u) == up->left)
273 up->left = rb_node_index (rt, v);
275 up->right = rb_node_index (rt, v);
276 v->parent = u->parent;
280 rb_tree_del_node (rb_tree_t * rt, rb_node_t * z)
282 rb_node_color_t y_original_color;
283 rb_node_t *x, *y, *yr, *yl, *xp, *w, *wl, *wr;
284 rb_node_index_t xi, yi;
287 y_original_color = y->color;
289 if (z->left == RBTREE_TNIL_INDEX)
291 x = rb_node_right (rt, z);
292 rb_tree_transplant (rt, z, x);
294 else if (z->right == RBTREE_TNIL_INDEX)
296 x = rb_node_left (rt, z);
297 rb_tree_transplant (rt, z, x);
301 y = rb_tree_min_subtree (rt, rb_node_right (rt, z));
302 y_original_color = y->color;
303 x = rb_node_right (rt, y);
304 yi = rb_node_index (rt, y);
305 if (y->parent == rb_node_index (rt, z))
309 rb_tree_transplant (rt, y, rb_node_right (rt, y));
311 yr = rb_node_right (rt, y);
314 rb_tree_transplant (rt, z, y);
316 yl = rb_node_left (rt, y);
321 if (y_original_color == RBTREE_RED)
324 /* Tree fixup needed */
326 xi = rb_node_index (rt, x);
327 while (xi != rt->root && x->color == RBTREE_BLACK)
329 xp = rb_node_parent (rt, x);
332 w = rb_node_right (rt, xp);
333 if (w->color == RBTREE_RED)
335 w->color = RBTREE_BLACK;
336 xp->color = RBTREE_RED;
337 rb_tree_rotate_left (rt, xp);
338 w = rb_node_right (rt, xp);
340 wl = rb_node_left (rt, w);
341 wr = rb_node_right (rt, w);
342 if (wl->color == RBTREE_BLACK && wr->color == RBTREE_BLACK)
344 w->color = RBTREE_RED;
349 if (wr->color == RBTREE_BLACK)
351 wl->color = RBTREE_BLACK;
352 w->color = RBTREE_RED;
353 rb_tree_rotate_right (rt, w);
354 w = rb_node_right (rt, xp);
356 w->color = xp->color;
357 xp->color = RBTREE_BLACK;
358 wr->color = RBTREE_BLACK;
359 rb_tree_rotate_left (rt, xp);
360 x = rb_node (rt, rt->root);
365 w = rb_node_left (rt, xp);
366 if (w->color == RBTREE_RED)
368 w->color = RBTREE_BLACK;
369 xp->color = RBTREE_RED;
370 rb_tree_rotate_right (rt, xp);
371 w = rb_node_left (rt, xp);
373 wl = rb_node_left (rt, w);
374 wr = rb_node_right (rt, w);
375 if (wl->color == RBTREE_BLACK && wr->color == RBTREE_BLACK)
377 w->color = RBTREE_RED;
382 if (wl->color == RBTREE_BLACK)
384 wr->color = RBTREE_BLACK;
385 w->color = RBTREE_RED;
386 rb_tree_rotate_left (rt, w);
387 w = rb_node_left (rt, xp);
389 w->color = xp->color;
390 xp->color = RBTREE_BLACK;
391 wl->color = RBTREE_BLACK;
392 rb_tree_rotate_right (rt, xp);
393 x = rb_node (rt, rt->root);
396 xi = rb_node_index (rt, x);
398 x->color = RBTREE_BLACK;
402 rb_tree_del (rb_tree_t * rt, u32 key)
405 n = rb_tree_search_subtree (rt, rb_node (rt, rt->root), key);
406 if (rb_node_index (rt, n) != RBTREE_TNIL_INDEX)
408 rb_tree_del_node (rt, n);
409 pool_put (rt->nodes, n);
414 rb_tree_n_nodes (rb_tree_t * rt)
416 return pool_elts (rt->nodes);
420 rb_tree_free_nodes (rb_tree_t * rt)
423 pool_flush (n, rt->nodes,;);
427 rb_tree_init (rb_tree_t * rt)
432 rt->root = RBTREE_TNIL_INDEX;
434 /* By convention first node, index 0, is the T.nil sentinel */
435 pool_get_zero (rt->nodes, tnil);
436 tnil->color = RBTREE_BLACK;
440 * fd.io coding-style-patch-verification: ON
443 * eval: (c-set-style "gnu")