summaryrefslogtreecommitdiff
path: root/src/common/tree.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/tree.h')
-rw-r--r--src/common/tree.h674
1 files changed, 674 insertions, 0 deletions
diff --git a/src/common/tree.h b/src/common/tree.h
new file mode 100644
index 000000000..3da49e422
--- /dev/null
+++ b/src/common/tree.h
@@ -0,0 +1,674 @@
1/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
2/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
3/* $FreeBSD$ */
4
5/*-
6 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#pragma once
31
32/*
33 * This file defines data structures for red-black trees.
34 *
35 * A red-black tree is a binary search tree with the node color as an
36 * extra attribute. It fulfills a set of conditions:
37 * - every search path from the root to a leaf consists of the
38 * same number of black nodes,
39 * - each red node (except for the root) has a black parent,
40 * - each leaf node is black.
41 *
42 * Every operation on a red-black tree is bounded as O(lg n).
43 * The maximum height of a red-black tree is 2lg (n+1).
44 */
45
46namespace Common {
47template <typename T>
48class RBHead {
49public:
50 [[nodiscard]] T* Root() {
51 return rbh_root;
52 }
53
54 [[nodiscard]] const T* Root() const {
55 return rbh_root;
56 }
57
58 void SetRoot(T* root) {
59 rbh_root = root;
60 }
61
62 [[nodiscard]] bool IsEmpty() const {
63 return Root() == nullptr;
64 }
65
66private:
67 T* rbh_root = nullptr;
68};
69
70enum class EntryColor {
71 Black,
72 Red,
73};
74
75template <typename T>
76class RBEntry {
77public:
78 [[nodiscard]] T* Left() {
79 return rbe_left;
80 }
81
82 [[nodiscard]] const T* Left() const {
83 return rbe_left;
84 }
85
86 void SetLeft(T* left) {
87 rbe_left = left;
88 }
89
90 [[nodiscard]] T* Right() {
91 return rbe_right;
92 }
93
94 [[nodiscard]] const T* Right() const {
95 return rbe_right;
96 }
97
98 void SetRight(T* right) {
99 rbe_right = right;
100 }
101
102 [[nodiscard]] T* Parent() {
103 return rbe_parent;
104 }
105
106 [[nodiscard]] const T* Parent() const {
107 return rbe_parent;
108 }
109
110 void SetParent(T* parent) {
111 rbe_parent = parent;
112 }
113
114 [[nodiscard]] bool IsBlack() const {
115 return rbe_color == EntryColor::Black;
116 }
117
118 [[nodiscard]] bool IsRed() const {
119 return rbe_color == EntryColor::Red;
120 }
121
122 [[nodiscard]] EntryColor Color() const {
123 return rbe_color;
124 }
125
126 void SetColor(EntryColor color) {
127 rbe_color = color;
128 }
129
130private:
131 T* rbe_left = nullptr;
132 T* rbe_right = nullptr;
133 T* rbe_parent = nullptr;
134 EntryColor rbe_color{};
135};
136
137template <typename Node>
138[[nodiscard]] RBEntry<Node>& RB_ENTRY(Node* node) {
139 return node->GetEntry();
140}
141
142template <typename Node>
143[[nodiscard]] const RBEntry<Node>& RB_ENTRY(const Node* node) {
144 return node->GetEntry();
145}
146
147template <typename Node>
148[[nodiscard]] Node* RB_PARENT(Node* node) {
149 return RB_ENTRY(node).Parent();
150}
151
152template <typename Node>
153[[nodiscard]] const Node* RB_PARENT(const Node* node) {
154 return RB_ENTRY(node).Parent();
155}
156
157template <typename Node>
158void RB_SET_PARENT(Node* node, Node* parent) {
159 return RB_ENTRY(node).SetParent(parent);
160}
161
162template <typename Node>
163[[nodiscard]] Node* RB_LEFT(Node* node) {
164 return RB_ENTRY(node).Left();
165}
166
167template <typename Node>
168[[nodiscard]] const Node* RB_LEFT(const Node* node) {
169 return RB_ENTRY(node).Left();
170}
171
172template <typename Node>
173void RB_SET_LEFT(Node* node, Node* left) {
174 return RB_ENTRY(node).SetLeft(left);
175}
176
177template <typename Node>
178[[nodiscard]] Node* RB_RIGHT(Node* node) {
179 return RB_ENTRY(node).Right();
180}
181
182template <typename Node>
183[[nodiscard]] const Node* RB_RIGHT(const Node* node) {
184 return RB_ENTRY(node).Right();
185}
186
187template <typename Node>
188void RB_SET_RIGHT(Node* node, Node* right) {
189 return RB_ENTRY(node).SetRight(right);
190}
191
192template <typename Node>
193[[nodiscard]] bool RB_IS_BLACK(const Node* node) {
194 return RB_ENTRY(node).IsBlack();
195}
196
197template <typename Node>
198[[nodiscard]] bool RB_IS_RED(const Node* node) {
199 return RB_ENTRY(node).IsRed();
200}
201
202template <typename Node>
203[[nodiscard]] EntryColor RB_COLOR(const Node* node) {
204 return RB_ENTRY(node).Color();
205}
206
207template <typename Node>
208void RB_SET_COLOR(Node* node, EntryColor color) {
209 return RB_ENTRY(node).SetColor(color);
210}
211
212template <typename Node>
213void RB_SET(Node* node, Node* parent) {
214 auto& entry = RB_ENTRY(node);
215 entry.SetParent(parent);
216 entry.SetLeft(nullptr);
217 entry.SetRight(nullptr);
218 entry.SetColor(EntryColor::Red);
219}
220
221template <typename Node>
222void RB_SET_BLACKRED(Node* black, Node* red) {
223 RB_SET_COLOR(black, EntryColor::Black);
224 RB_SET_COLOR(red, EntryColor::Red);
225}
226
227template <typename Node>
228void RB_ROTATE_LEFT(RBHead<Node>* head, Node* elm, Node*& tmp) {
229 tmp = RB_RIGHT(elm);
230 RB_SET_RIGHT(elm, RB_LEFT(tmp));
231 if (RB_RIGHT(elm) != nullptr) {
232 RB_SET_PARENT(RB_LEFT(tmp), elm);
233 }
234
235 RB_SET_PARENT(tmp, RB_PARENT(elm));
236 if (RB_PARENT(tmp) != nullptr) {
237 if (elm == RB_LEFT(RB_PARENT(elm))) {
238 RB_SET_LEFT(RB_PARENT(elm), tmp);
239 } else {
240 RB_SET_RIGHT(RB_PARENT(elm), tmp);
241 }
242 } else {
243 head->SetRoot(tmp);
244 }
245
246 RB_SET_LEFT(tmp, elm);
247 RB_SET_PARENT(elm, tmp);
248}
249
250template <typename Node>
251void RB_ROTATE_RIGHT(RBHead<Node>* head, Node* elm, Node*& tmp) {
252 tmp = RB_LEFT(elm);
253 RB_SET_LEFT(elm, RB_RIGHT(tmp));
254 if (RB_LEFT(elm) != nullptr) {
255 RB_SET_PARENT(RB_RIGHT(tmp), elm);
256 }
257
258 RB_SET_PARENT(tmp, RB_PARENT(elm));
259 if (RB_PARENT(tmp) != nullptr) {
260 if (elm == RB_LEFT(RB_PARENT(elm))) {
261 RB_SET_LEFT(RB_PARENT(elm), tmp);
262 } else {
263 RB_SET_RIGHT(RB_PARENT(elm), tmp);
264 }
265 } else {
266 head->SetRoot(tmp);
267 }
268
269 RB_SET_RIGHT(tmp, elm);
270 RB_SET_PARENT(elm, tmp);
271}
272
273template <typename Node>
274void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) {
275 Node* parent = nullptr;
276 Node* tmp = nullptr;
277
278 while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) {
279 Node* gparent = RB_PARENT(parent);
280 if (parent == RB_LEFT(gparent)) {
281 tmp = RB_RIGHT(gparent);
282 if (tmp && RB_IS_RED(tmp)) {
283 RB_SET_COLOR(tmp, EntryColor::Black);
284 RB_SET_BLACKRED(parent, gparent);
285 elm = gparent;
286 continue;
287 }
288
289 if (RB_RIGHT(parent) == elm) {
290 RB_ROTATE_LEFT(head, parent, tmp);
291 tmp = parent;
292 parent = elm;
293 elm = tmp;
294 }
295
296 RB_SET_BLACKRED(parent, gparent);
297 RB_ROTATE_RIGHT(head, gparent, tmp);
298 } else {
299 tmp = RB_LEFT(gparent);
300 if (tmp && RB_IS_RED(tmp)) {
301 RB_SET_COLOR(tmp, EntryColor::Black);
302 RB_SET_BLACKRED(parent, gparent);
303 elm = gparent;
304 continue;
305 }
306
307 if (RB_LEFT(parent) == elm) {
308 RB_ROTATE_RIGHT(head, parent, tmp);
309 tmp = parent;
310 parent = elm;
311 elm = tmp;
312 }
313
314 RB_SET_BLACKRED(parent, gparent);
315 RB_ROTATE_LEFT(head, gparent, tmp);
316 }
317 }
318
319 RB_SET_COLOR(head->Root(), EntryColor::Black);
320}
321
322template <typename Node>
323void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) {
324 Node* tmp;
325 while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root()) {
326 if (RB_LEFT(parent) == elm) {
327 tmp = RB_RIGHT(parent);
328 if (RB_IS_RED(tmp)) {
329 RB_SET_BLACKRED(tmp, parent);
330 RB_ROTATE_LEFT(head, parent, tmp);
331 tmp = RB_RIGHT(parent);
332 }
333
334 if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) &&
335 (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) {
336 RB_SET_COLOR(tmp, EntryColor::Red);
337 elm = parent;
338 parent = RB_PARENT(elm);
339 } else {
340 if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) {
341 Node* oleft;
342 if ((oleft = RB_LEFT(tmp)) != nullptr) {
343 RB_SET_COLOR(oleft, EntryColor::Black);
344 }
345
346 RB_SET_COLOR(tmp, EntryColor::Red);
347 RB_ROTATE_RIGHT(head, tmp, oleft);
348 tmp = RB_RIGHT(parent);
349 }
350
351 RB_SET_COLOR(tmp, RB_COLOR(parent));
352 RB_SET_COLOR(parent, EntryColor::Black);
353 if (RB_RIGHT(tmp)) {
354 RB_SET_COLOR(RB_RIGHT(tmp), EntryColor::Black);
355 }
356
357 RB_ROTATE_LEFT(head, parent, tmp);
358 elm = head->Root();
359 break;
360 }
361 } else {
362 tmp = RB_LEFT(parent);
363 if (RB_IS_RED(tmp)) {
364 RB_SET_BLACKRED(tmp, parent);
365 RB_ROTATE_RIGHT(head, parent, tmp);
366 tmp = RB_LEFT(parent);
367 }
368
369 if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) &&
370 (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) {
371 RB_SET_COLOR(tmp, EntryColor::Red);
372 elm = parent;
373 parent = RB_PARENT(elm);
374 } else {
375 if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) {
376 Node* oright;
377 if ((oright = RB_RIGHT(tmp)) != nullptr) {
378 RB_SET_COLOR(oright, EntryColor::Black);
379 }
380
381 RB_SET_COLOR(tmp, EntryColor::Red);
382 RB_ROTATE_LEFT(head, tmp, oright);
383 tmp = RB_LEFT(parent);
384 }
385
386 RB_SET_COLOR(tmp, RB_COLOR(parent));
387 RB_SET_COLOR(parent, EntryColor::Black);
388
389 if (RB_LEFT(tmp)) {
390 RB_SET_COLOR(RB_LEFT(tmp), EntryColor::Black);
391 }
392
393 RB_ROTATE_RIGHT(head, parent, tmp);
394 elm = head->Root();
395 break;
396 }
397 }
398 }
399
400 if (elm) {
401 RB_SET_COLOR(elm, EntryColor::Black);
402 }
403}
404
405template <typename Node>
406Node* RB_REMOVE(RBHead<Node>* head, Node* elm) {
407 Node* child = nullptr;
408 Node* parent = nullptr;
409 Node* old = elm;
410 EntryColor color{};
411
412 const auto finalize = [&] {
413 if (color == EntryColor::Black) {
414 RB_REMOVE_COLOR(head, parent, child);
415 }
416
417 return old;
418 };
419
420 if (RB_LEFT(elm) == nullptr) {
421 child = RB_RIGHT(elm);
422 } else if (RB_RIGHT(elm) == nullptr) {
423 child = RB_LEFT(elm);
424 } else {
425 Node* left;
426 elm = RB_RIGHT(elm);
427 while ((left = RB_LEFT(elm)) != nullptr) {
428 elm = left;
429 }
430
431 child = RB_RIGHT(elm);
432 parent = RB_PARENT(elm);
433 color = RB_COLOR(elm);
434
435 if (child) {
436 RB_SET_PARENT(child, parent);
437 }
438 if (parent) {
439 if (RB_LEFT(parent) == elm) {
440 RB_SET_LEFT(parent, child);
441 } else {
442 RB_SET_RIGHT(parent, child);
443 }
444 } else {
445 head->SetRoot(child);
446 }
447
448 if (RB_PARENT(elm) == old) {
449 parent = elm;
450 }
451
452 elm->SetEntry(old->GetEntry());
453
454 if (RB_PARENT(old)) {
455 if (RB_LEFT(RB_PARENT(old)) == old) {
456 RB_SET_LEFT(RB_PARENT(old), elm);
457 } else {
458 RB_SET_RIGHT(RB_PARENT(old), elm);
459 }
460 } else {
461 head->SetRoot(elm);
462 }
463 RB_SET_PARENT(RB_LEFT(old), elm);
464 if (RB_RIGHT(old)) {
465 RB_SET_PARENT(RB_RIGHT(old), elm);
466 }
467 if (parent) {
468 left = parent;
469 }
470
471 return finalize();
472 }
473
474 parent = RB_PARENT(elm);
475 color = RB_COLOR(elm);
476
477 if (child) {
478 RB_SET_PARENT(child, parent);
479 }
480 if (parent) {
481 if (RB_LEFT(parent) == elm) {
482 RB_SET_LEFT(parent, child);
483 } else {
484 RB_SET_RIGHT(parent, child);
485 }
486 } else {
487 head->SetRoot(child);
488 }
489
490 return finalize();
491}
492
493// Inserts a node into the RB tree
494template <typename Node, typename CompareFunction>
495Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
496 Node* parent = nullptr;
497 Node* tmp = head->Root();
498 int comp = 0;
499
500 while (tmp) {
501 parent = tmp;
502 comp = cmp(elm, parent);
503 if (comp < 0) {
504 tmp = RB_LEFT(tmp);
505 } else if (comp > 0) {
506 tmp = RB_RIGHT(tmp);
507 } else {
508 return tmp;
509 }
510 }
511
512 RB_SET(elm, parent);
513
514 if (parent != nullptr) {
515 if (comp < 0) {
516 RB_SET_LEFT(parent, elm);
517 } else {
518 RB_SET_RIGHT(parent, elm);
519 }
520 } else {
521 head->SetRoot(elm);
522 }
523
524 RB_INSERT_COLOR(head, elm);
525 return nullptr;
526}
527
528// Finds the node with the same key as elm
529template <typename Node, typename CompareFunction>
530Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
531 Node* tmp = head->Root();
532
533 while (tmp) {
534 const int comp = cmp(elm, tmp);
535 if (comp < 0) {
536 tmp = RB_LEFT(tmp);
537 } else if (comp > 0) {
538 tmp = RB_RIGHT(tmp);
539 } else {
540 return tmp;
541 }
542 }
543
544 return nullptr;
545}
546
547// Finds the first node greater than or equal to the search key
548template <typename Node, typename CompareFunction>
549Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) {
550 Node* tmp = head->Root();
551 Node* res = nullptr;
552
553 while (tmp) {
554 const int comp = cmp(elm, tmp);
555 if (comp < 0) {
556 res = tmp;
557 tmp = RB_LEFT(tmp);
558 } else if (comp > 0) {
559 tmp = RB_RIGHT(tmp);
560 } else {
561 return tmp;
562 }
563 }
564
565 return res;
566}
567
568// Finds the node with the same key as lelm
569template <typename Node, typename CompareFunction>
570Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) {
571 Node* tmp = head->Root();
572
573 while (tmp) {
574 const int comp = lcmp(lelm, tmp);
575 if (comp < 0) {
576 tmp = RB_LEFT(tmp);
577 } else if (comp > 0) {
578 tmp = RB_RIGHT(tmp);
579 } else {
580 return tmp;
581 }
582 }
583
584 return nullptr;
585}
586
587// Finds the first node greater than or equal to the search key
588template <typename Node, typename CompareFunction>
589Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) {
590 Node* tmp = head->Root();
591 Node* res = nullptr;
592
593 while (tmp) {
594 const int comp = lcmp(lelm, tmp);
595 if (comp < 0) {
596 res = tmp;
597 tmp = RB_LEFT(tmp);
598 } else if (comp > 0) {
599 tmp = RB_RIGHT(tmp);
600 } else {
601 return tmp;
602 }
603 }
604
605 return res;
606}
607
608template <typename Node>
609Node* RB_NEXT(Node* elm) {
610 if (RB_RIGHT(elm)) {
611 elm = RB_RIGHT(elm);
612 while (RB_LEFT(elm)) {
613 elm = RB_LEFT(elm);
614 }
615 } else {
616 if (RB_PARENT(elm) && (elm == RB_LEFT(RB_PARENT(elm)))) {
617 elm = RB_PARENT(elm);
618 } else {
619 while (RB_PARENT(elm) && (elm == RB_RIGHT(RB_PARENT(elm)))) {
620 elm = RB_PARENT(elm);
621 }
622 elm = RB_PARENT(elm);
623 }
624 }
625 return elm;
626}
627
628template <typename Node>
629Node* RB_PREV(Node* elm) {
630 if (RB_LEFT(elm)) {
631 elm = RB_LEFT(elm);
632 while (RB_RIGHT(elm)) {
633 elm = RB_RIGHT(elm);
634 }
635 } else {
636 if (RB_PARENT(elm) && (elm == RB_RIGHT(RB_PARENT(elm)))) {
637 elm = RB_PARENT(elm);
638 } else {
639 while (RB_PARENT(elm) && (elm == RB_LEFT(RB_PARENT(elm)))) {
640 elm = RB_PARENT(elm);
641 }
642 elm = RB_PARENT(elm);
643 }
644 }
645 return elm;
646}
647
648template <typename Node>
649Node* RB_MINMAX(RBHead<Node>* head, bool is_min) {
650 Node* tmp = head->Root();
651 Node* parent = nullptr;
652
653 while (tmp) {
654 parent = tmp;
655 if (is_min) {
656 tmp = RB_LEFT(tmp);
657 } else {
658 tmp = RB_RIGHT(tmp);
659 }
660 }
661
662 return parent;
663}
664
665template <typename Node>
666Node* RB_MIN(RBHead<Node>* head) {
667 return RB_MINMAX(head, true);
668}
669
670template <typename Node>
671Node* RB_MAX(RBHead<Node>* head) {
672 return RB_MINMAX(head, false);
673}
674} // namespace Common