/src/open5gs/lib/core/ogs-rbtree.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com> |
3 | | * |
4 | | * This file is part of Open5GS. |
5 | | * |
6 | | * This program is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Affero General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | #include "ogs-core.h" |
21 | | |
22 | | static ogs_inline void rb_change_child(ogs_rbtree_t *tree, |
23 | | ogs_rbnode_t *old, ogs_rbnode_t *new, ogs_rbnode_t *parent) |
24 | 4.95k | { |
25 | 4.95k | if (parent) { |
26 | 4.42k | if (old == parent->left) |
27 | 1.98k | parent->left = new; |
28 | 2.43k | else |
29 | 2.43k | parent->right = new; |
30 | 4.42k | } else { |
31 | 526 | tree->root = new; |
32 | 526 | } |
33 | 4.95k | } |
34 | | |
35 | | static ogs_inline void rb_replace_node(ogs_rbtree_t *tree, |
36 | | ogs_rbnode_t *old, ogs_rbnode_t *new, ogs_rbnode_t *parent) |
37 | 4.95k | { |
38 | 4.95k | rb_change_child(tree, old, new, parent); |
39 | | |
40 | 4.95k | if (new) |
41 | 4.95k | new->parent = parent; |
42 | 4.95k | } |
43 | | |
44 | | /* |
45 | | * Example - Left rotate at A |
46 | | * |
47 | | * A B |
48 | | * / \ / \ |
49 | | * B C <-- D A |
50 | | * / \ / \ / \ / \ |
51 | | * D 3 4 5 1 2 3 C |
52 | | * / \ / \ |
53 | | * 1 2 1 2 |
54 | | */ |
55 | | static void rb_rotate_left(ogs_rbtree_t *tree, ogs_rbnode_t *node) |
56 | 2.78k | { |
57 | 2.78k | ogs_rbnode_t *right = node->right; |
58 | 2.78k | node->right = right->left; |
59 | 2.78k | if (right->left) |
60 | 985 | right->left->parent = node; |
61 | | |
62 | 2.78k | rb_replace_node(tree, node, right, node->parent); |
63 | | |
64 | 2.78k | right->left = node; |
65 | 2.78k | node->parent = right; |
66 | 2.78k | } |
67 | | |
68 | | /* |
69 | | * Example - right rotate at A |
70 | | * |
71 | | * A B |
72 | | * / \ / \ |
73 | | * B C --> D A |
74 | | * / \ / \ / \ / \ |
75 | | * D 3 4 5 1 2 3 C |
76 | | * / \ / \ |
77 | | * 1 2 1 2 |
78 | | */ |
79 | | static void rb_rotate_right(ogs_rbtree_t *tree, ogs_rbnode_t *node) |
80 | 2.16k | { |
81 | 2.16k | ogs_rbnode_t *left = node->left; |
82 | 2.16k | node->left = left->right; |
83 | 2.16k | if (left->right) |
84 | 602 | left->right->parent = node; |
85 | | |
86 | 2.16k | rb_replace_node(tree, node, left, node->parent); |
87 | | |
88 | 2.16k | left->right = node; |
89 | 2.16k | node->parent = left; |
90 | 2.16k | } |
91 | | |
92 | | void ogs_rbtree_insert_color(ogs_rbtree_t *tree, void *rb_node) |
93 | 6.43k | { |
94 | 6.43k | ogs_rbnode_t *node = rb_node; |
95 | 6.43k | ogs_rbnode_t *parent; |
96 | 6.43k | ogs_assert(tree); |
97 | 6.43k | ogs_assert(node); |
98 | | |
99 | 12.9k | while ((parent = node->parent) && parent->color == OGS_RBTREE_RED) { |
100 | 6.54k | ogs_rbnode_t *gparent = parent->parent; |
101 | 6.54k | ogs_assert(gparent); |
102 | | |
103 | | /* parent == grandparent's left child */ |
104 | 6.54k | if (parent == gparent->left) { |
105 | 2.56k | ogs_rbnode_t *uncle = gparent->right; |
106 | | |
107 | 2.56k | if (uncle && uncle->color == OGS_RBTREE_RED) { |
108 | | /* |
109 | | * node's uncle == red (color flips) |
110 | | * |
111 | | * G g |
112 | | * / \ / \ |
113 | | * p u --> P U |
114 | | * / / |
115 | | * n n |
116 | | */ |
117 | 1.06k | uncle->color = OGS_RBTREE_BLACK; |
118 | 1.06k | parent->color = OGS_RBTREE_BLACK; |
119 | | |
120 | 1.06k | gparent->color = OGS_RBTREE_RED; |
121 | | |
122 | 1.06k | node = gparent; |
123 | 1.50k | } else { |
124 | | /* node's uncle == black */ |
125 | 1.50k | if (node == parent->right) { |
126 | | /* |
127 | | * node == the parent's right child, |
128 | | * (left rotate at parent) |
129 | | * |
130 | | * G G |
131 | | * / \ / \ |
132 | | * p U --> p U |
133 | | * \ / |
134 | | * n n |
135 | | */ |
136 | 938 | node = node->parent; |
137 | 938 | rb_rotate_left(tree, node); |
138 | 938 | } |
139 | | |
140 | | /* |
141 | | * Now we're the left child |
142 | | * (right rotate at grand parent) |
143 | | * |
144 | | * g P |
145 | | * / \ / \ |
146 | | * P U --> n g |
147 | | * / \ |
148 | | * n U |
149 | | */ |
150 | 1.50k | node->parent->color = OGS_RBTREE_BLACK; |
151 | 1.50k | gparent->color = OGS_RBTREE_RED; |
152 | 1.50k | rb_rotate_right(tree, gparent); |
153 | 1.50k | } |
154 | | /* parent == grandparent's right child */ |
155 | 3.97k | } else { |
156 | 3.97k | ogs_rbnode_t *uncle = gparent->left; |
157 | | |
158 | 3.97k | if (uncle && uncle->color == OGS_RBTREE_RED) { |
159 | | /* |
160 | | * node's uncle == red (color flips) |
161 | | * |
162 | | * G g |
163 | | * / \ / \ |
164 | | * u p --> U P |
165 | | * \ \ |
166 | | * n n |
167 | | */ |
168 | 2.12k | uncle->color = OGS_RBTREE_BLACK; |
169 | 2.12k | parent->color = OGS_RBTREE_BLACK; |
170 | | |
171 | 2.12k | gparent->color = OGS_RBTREE_RED; |
172 | | |
173 | 2.12k | node = gparent; |
174 | 2.12k | } else { |
175 | | /* node's uncle == black */ |
176 | 1.85k | if (node == parent->left) { |
177 | | /* |
178 | | * node == the parent's left child, |
179 | | * (right rotate at parent) |
180 | | * |
181 | | * G G |
182 | | * / \ / \ |
183 | | * p U --> p U |
184 | | * / \ |
185 | | * n n |
186 | | */ |
187 | 659 | node = node->parent; |
188 | 659 | rb_rotate_right(tree, node); |
189 | 659 | } |
190 | | |
191 | | /* |
192 | | * Now we're the right child, |
193 | | * (left rotate at grand parent) |
194 | | * |
195 | | * g P |
196 | | * / \ / \ |
197 | | * P U --> n g |
198 | | * \ \ |
199 | | * n U |
200 | | */ |
201 | 1.85k | node->parent->color = OGS_RBTREE_BLACK; |
202 | 1.85k | gparent->color = OGS_RBTREE_RED; |
203 | 1.85k | rb_rotate_left(tree, gparent); |
204 | 1.85k | } |
205 | 3.97k | } |
206 | 6.54k | } |
207 | | |
208 | 6.43k | ogs_assert(tree->root); |
209 | 6.43k | tree->root->color = OGS_RBTREE_BLACK; |
210 | 6.43k | } |
211 | | |
212 | | static void rb_delete_color( |
213 | | ogs_rbtree_t *tree, ogs_rbnode_t *node, ogs_rbnode_t *parent) |
214 | 0 | { |
215 | 0 | ogs_rbnode_t *sibling; |
216 | 0 | ogs_assert(tree); |
217 | | |
218 | 0 | #define rb_is_black(r) ((!r) || (r)->color == OGS_RBTREE_BLACK) |
219 | 0 | while (node != tree->root && rb_is_black(node)) { |
220 | 0 | if (node == parent->left) { |
221 | 0 | sibling = parent->right; |
222 | 0 | if (sibling->color == OGS_RBTREE_RED) { |
223 | | /* |
224 | | * Case 1 - left rotate at parent |
225 | | * |
226 | | * P S |
227 | | * / \ / \ |
228 | | * N s --> p Sr |
229 | | * / \ / \ |
230 | | * Sl Sr N Sl |
231 | | */ |
232 | 0 | sibling->color = OGS_RBTREE_BLACK; |
233 | 0 | parent->color = OGS_RBTREE_RED; |
234 | 0 | rb_rotate_left(tree, parent); |
235 | 0 | sibling = parent->right; |
236 | 0 | } |
237 | 0 | if (rb_is_black(sibling->left) && rb_is_black(sibling->right)) { |
238 | | /* |
239 | | * Case 2 - sibling color flip |
240 | | * (p could be either color here) |
241 | | * |
242 | | * (p) (p) |
243 | | * / \ / \ |
244 | | * N S --> N s |
245 | | * / \ / \ |
246 | | * Sl Sr Sl Sr |
247 | | */ |
248 | 0 | sibling->color = OGS_RBTREE_RED; |
249 | 0 | node = parent; |
250 | 0 | parent = node->parent; |
251 | 0 | } else { |
252 | 0 | if (rb_is_black(sibling->right)) { |
253 | | /* |
254 | | * Case 3 - right rotate at sibling |
255 | | * (p could be either color here) |
256 | | * |
257 | | * (p) (p) |
258 | | * / \ / \ |
259 | | * N S --> N Sl |
260 | | * / \ \ |
261 | | * sl Sr s |
262 | | * \ |
263 | | * Sr |
264 | | */ |
265 | 0 | sibling->left->color = OGS_RBTREE_BLACK; |
266 | 0 | sibling->color = OGS_RBTREE_RED; |
267 | 0 | rb_rotate_right(tree, sibling); |
268 | 0 | sibling = parent->right; |
269 | 0 | } |
270 | | /* |
271 | | * Case 4 - left rotate at parent + color flips |
272 | | * (p and sl could be either color here. |
273 | | * After rotation, p becomes black, s acquires |
274 | | * p's color, and sl keeps its color) |
275 | | * |
276 | | * (p) (s) |
277 | | * / \ / \ |
278 | | * N S --> P Sr |
279 | | * / \ / \ |
280 | | * (sl) sr N (sl) |
281 | | */ |
282 | 0 | sibling->color = parent->color; |
283 | 0 | parent->color = OGS_RBTREE_BLACK; |
284 | 0 | sibling->right->color = OGS_RBTREE_BLACK; |
285 | 0 | rb_rotate_left(tree, parent); |
286 | 0 | node = tree->root; |
287 | 0 | } |
288 | 0 | } else { |
289 | 0 | sibling = parent->left; |
290 | 0 | if (sibling->color == OGS_RBTREE_RED) { |
291 | 0 | sibling->color = OGS_RBTREE_BLACK; |
292 | 0 | parent->color = OGS_RBTREE_RED; |
293 | | /* Case 1 - right rotate at parent */ |
294 | 0 | rb_rotate_right(tree, parent); |
295 | 0 | sibling = parent->left; |
296 | 0 | } |
297 | 0 | if (rb_is_black(sibling->left) && rb_is_black(sibling->right)) { |
298 | | /* Case 2 - sibling color flip */ |
299 | 0 | sibling->color = OGS_RBTREE_RED; |
300 | 0 | node = parent; |
301 | 0 | parent = node->parent; |
302 | 0 | } else { |
303 | 0 | if (rb_is_black(sibling->left)) { |
304 | 0 | sibling->right->color = OGS_RBTREE_BLACK; |
305 | 0 | sibling->color = OGS_RBTREE_RED; |
306 | | /* Case 3 - left rotate at sibling */ |
307 | 0 | rb_rotate_left(tree, sibling); |
308 | 0 | sibling = parent->left; |
309 | 0 | } |
310 | | /* Case 4 - right rotate at parent + color flips */ |
311 | 0 | sibling->color = parent->color; |
312 | 0 | parent->color = OGS_RBTREE_BLACK; |
313 | 0 | sibling->left->color = OGS_RBTREE_BLACK; |
314 | 0 | rb_rotate_right(tree, parent); |
315 | 0 | node = tree->root; |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | 0 | if (node) |
320 | 0 | node->color = OGS_RBTREE_BLACK; |
321 | 0 | } |
322 | | |
323 | | void ogs_rbtree_delete(ogs_rbtree_t *tree, void *rb_node) |
324 | 0 | { |
325 | 0 | ogs_rbnode_t *node = rb_node; |
326 | 0 | ogs_rbnode_t *child, *parent; |
327 | 0 | ogs_rbtree_color_e color; |
328 | 0 | ogs_assert(tree); |
329 | 0 | ogs_assert(node); |
330 | | |
331 | 0 | if (!node->left) { |
332 | 0 | child = node->right; |
333 | 0 | parent = node->parent; |
334 | 0 | color = node->color; |
335 | |
|
336 | 0 | rb_replace_node(tree, node, child, parent); |
337 | 0 | } else if (!node->right) { |
338 | 0 | child = node->left; |
339 | 0 | parent = node->parent; |
340 | 0 | color = node->color; |
341 | |
|
342 | 0 | rb_replace_node(tree, node, child, parent); |
343 | 0 | } else { |
344 | 0 | ogs_rbnode_t *new = ogs_rbtree_min(node->right); |
345 | |
|
346 | 0 | child = new->right; |
347 | 0 | parent = new->parent; |
348 | 0 | color = new->color; |
349 | |
|
350 | 0 | new->left = node->left; |
351 | 0 | node->left->parent = new; |
352 | |
|
353 | 0 | if (parent == node) { |
354 | 0 | parent = new; |
355 | 0 | } else { |
356 | 0 | if (child) { |
357 | 0 | child->parent = parent; |
358 | 0 | } |
359 | 0 | parent->left = child; |
360 | |
|
361 | 0 | new->right = node->right; |
362 | 0 | node->right->parent = new; |
363 | 0 | } |
364 | |
|
365 | 0 | new->color = node->color; |
366 | |
|
367 | 0 | rb_replace_node(tree, node, new, node->parent); |
368 | 0 | } |
369 | |
|
370 | 0 | if (color == OGS_RBTREE_BLACK) |
371 | 0 | rb_delete_color(tree, child, parent); |
372 | 0 | } |
373 | | |
374 | | void *ogs_rbtree_first(const ogs_rbtree_t *tree) |
375 | 0 | { |
376 | 0 | ogs_rbnode_t *node; |
377 | 0 | ogs_assert(tree); |
378 | | |
379 | 0 | node = tree->root; |
380 | 0 | if (!node) |
381 | 0 | return NULL; |
382 | | |
383 | 0 | return ogs_rbtree_min(node); |
384 | 0 | } |
385 | | |
386 | | void *ogs_rbtree_last(const ogs_rbtree_t *tree) |
387 | 0 | { |
388 | 0 | ogs_rbnode_t *node; |
389 | 0 | ogs_assert(tree); |
390 | | |
391 | 0 | node = tree->root; |
392 | 0 | if (!node) |
393 | 0 | return NULL; |
394 | | |
395 | 0 | return ogs_rbtree_max(node); |
396 | 0 | } |
397 | | |
398 | 0 | #define rb_empty_node(node) ((node)->parent == (node)) |
399 | | |
400 | | void *ogs_rbtree_next(const void *rb_node) |
401 | 0 | { |
402 | 0 | const ogs_rbnode_t *node = rb_node; |
403 | 0 | ogs_rbnode_t *parent; |
404 | 0 | ogs_assert(node); |
405 | | |
406 | 0 | if (rb_empty_node(node)) |
407 | 0 | return NULL; |
408 | | |
409 | 0 | if (node->right) |
410 | 0 | return ogs_rbtree_min(node->right); |
411 | | |
412 | 0 | while ((parent = node->parent) && node == parent->right) |
413 | 0 | node = parent; |
414 | |
|
415 | 0 | return parent; |
416 | 0 | } |
417 | | |
418 | | void *ogs_rbtree_prev(const void *rb_node) |
419 | 0 | { |
420 | 0 | const ogs_rbnode_t *node = rb_node; |
421 | 0 | ogs_rbnode_t *parent; |
422 | 0 | ogs_assert(node); |
423 | | |
424 | 0 | if (rb_empty_node(node)) |
425 | 0 | return NULL; |
426 | | |
427 | 0 | if (node->left) |
428 | 0 | return ogs_rbtree_max(node->left); |
429 | | |
430 | 0 | while ((parent = node->parent) && node == parent->left) |
431 | 0 | node = parent; |
432 | |
|
433 | 0 | return parent; |
434 | 0 | } |