Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/templates/rb_set.h
9973 views
1
/**************************************************************************/
2
/* rb_set.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/os/memory.h"
34
#include "core/typedefs.h"
35
36
#include <initializer_list>
37
38
// based on the very nice implementation of rb-trees by:
39
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
40
41
template <typename T, typename C = Comparator<T>, typename A = DefaultAllocator>
42
class RBSet {
43
enum Color {
44
RED,
45
BLACK
46
};
47
struct _Data;
48
49
public:
50
class Element {
51
private:
52
friend class RBSet<T, C, A>;
53
int color = RED;
54
Element *right = nullptr;
55
Element *left = nullptr;
56
Element *parent = nullptr;
57
Element *_next = nullptr;
58
Element *_prev = nullptr;
59
T value;
60
//_Data *data;
61
62
public:
63
const Element *next() const {
64
return _next;
65
}
66
Element *next() {
67
return _next;
68
}
69
const Element *prev() const {
70
return _prev;
71
}
72
Element *prev() {
73
return _prev;
74
}
75
T &get() {
76
return value;
77
}
78
const T &get() const {
79
return value;
80
}
81
Element() {}
82
};
83
84
typedef T ValueType;
85
86
struct Iterator {
87
_FORCE_INLINE_ T &operator*() const {
88
return E->get();
89
}
90
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
91
_FORCE_INLINE_ Iterator &operator++() {
92
E = E->next();
93
return *this;
94
}
95
_FORCE_INLINE_ Iterator &operator--() {
96
E = E->prev();
97
return *this;
98
}
99
100
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
101
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
102
103
explicit operator bool() const { return E != nullptr; }
104
Iterator(Element *p_E) { E = p_E; }
105
Iterator() {}
106
Iterator(const Iterator &p_it) { E = p_it.E; }
107
108
private:
109
Element *E = nullptr;
110
};
111
112
struct ConstIterator {
113
_FORCE_INLINE_ const T &operator*() const {
114
return E->get();
115
}
116
_FORCE_INLINE_ const T *operator->() const { return &E->get(); }
117
_FORCE_INLINE_ ConstIterator &operator++() {
118
E = E->next();
119
return *this;
120
}
121
_FORCE_INLINE_ ConstIterator &operator--() {
122
E = E->prev();
123
return *this;
124
}
125
126
_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
127
_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
128
129
_FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
130
_FORCE_INLINE_ ConstIterator() {}
131
_FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
132
133
explicit operator bool() const { return E != nullptr; }
134
135
private:
136
const Element *E = nullptr;
137
};
138
139
_FORCE_INLINE_ Iterator begin() {
140
return Iterator(front());
141
}
142
_FORCE_INLINE_ Iterator end() {
143
return Iterator(nullptr);
144
}
145
146
#if 0
147
//to use when replacing find()
148
_FORCE_INLINE_ Iterator find(const K &p_key) {
149
return Iterator(find(p_key));
150
}
151
#endif
152
153
_FORCE_INLINE_ ConstIterator begin() const {
154
return ConstIterator(front());
155
}
156
_FORCE_INLINE_ ConstIterator end() const {
157
return ConstIterator(nullptr);
158
}
159
160
#if 0
161
//to use when replacing find()
162
_FORCE_INLINE_ ConstIterator find(const K &p_key) const {
163
return ConstIterator(find(p_key));
164
}
165
#endif
166
private:
167
struct _Data {
168
Element *_root = nullptr;
169
Element *_nil = nullptr;
170
int size_cache = 0;
171
172
_FORCE_INLINE_ _Data() {
173
#ifdef GLOBALNIL_DISABLED
174
_nil = memnew_allocator(Element, A);
175
_nil->parent = _nil->left = _nil->right = _nil;
176
_nil->color = BLACK;
177
#else
178
_nil = (Element *)&_GlobalNilClass::_nil;
179
#endif
180
}
181
182
void _create_root() {
183
_root = memnew_allocator(Element, A);
184
_root->parent = _root->left = _root->right = _nil;
185
_root->color = BLACK;
186
}
187
188
void _free_root() {
189
if (_root) {
190
memdelete_allocator<Element, A>(_root);
191
_root = nullptr;
192
}
193
}
194
195
~_Data() {
196
_free_root();
197
198
#ifdef GLOBALNIL_DISABLED
199
memdelete_allocator<Element, A>(_nil);
200
#endif
201
}
202
};
203
204
_Data _data;
205
206
inline void _set_color(Element *p_node, int p_color) {
207
ERR_FAIL_COND(p_node == _data._nil && p_color == RED);
208
p_node->color = p_color;
209
}
210
211
inline void _rotate_left(Element *p_node) {
212
Element *r = p_node->right;
213
p_node->right = r->left;
214
if (r->left != _data._nil) {
215
r->left->parent = p_node;
216
}
217
r->parent = p_node->parent;
218
if (p_node == p_node->parent->left) {
219
p_node->parent->left = r;
220
} else {
221
p_node->parent->right = r;
222
}
223
224
r->left = p_node;
225
p_node->parent = r;
226
}
227
228
inline void _rotate_right(Element *p_node) {
229
Element *l = p_node->left;
230
p_node->left = l->right;
231
if (l->right != _data._nil) {
232
l->right->parent = p_node;
233
}
234
l->parent = p_node->parent;
235
if (p_node == p_node->parent->right) {
236
p_node->parent->right = l;
237
} else {
238
p_node->parent->left = l;
239
}
240
241
l->right = p_node;
242
p_node->parent = l;
243
}
244
245
inline Element *_successor(Element *p_node) const {
246
Element *node = p_node;
247
248
if (node->right != _data._nil) {
249
node = node->right;
250
while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */
251
node = node->left;
252
}
253
return node;
254
} else {
255
while (node == node->parent->right) {
256
node = node->parent;
257
}
258
259
if (node->parent == _data._root) {
260
return nullptr; // No successor, as p_node = last node
261
}
262
return node->parent;
263
}
264
}
265
266
inline Element *_predecessor(Element *p_node) const {
267
Element *node = p_node;
268
269
if (node->left != _data._nil) {
270
node = node->left;
271
while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */
272
node = node->right;
273
}
274
return node;
275
} else {
276
while (node == node->parent->left) {
277
node = node->parent;
278
}
279
280
if (node == _data._root) {
281
return nullptr; // No predecessor, as p_node = first node.
282
}
283
return node->parent;
284
}
285
}
286
287
Element *_find(const T &p_value) const {
288
Element *node = _data._root->left;
289
C less;
290
291
while (node != _data._nil) {
292
if (less(p_value, node->value)) {
293
node = node->left;
294
} else if (less(node->value, p_value)) {
295
node = node->right;
296
} else {
297
return node; // found
298
}
299
}
300
301
return nullptr;
302
}
303
304
Element *_lower_bound(const T &p_value) const {
305
Element *node = _data._root->left;
306
Element *prev = nullptr;
307
C less;
308
309
while (node != _data._nil) {
310
prev = node;
311
312
if (less(p_value, node->value)) {
313
node = node->left;
314
} else if (less(node->value, p_value)) {
315
node = node->right;
316
} else {
317
return node; // found
318
}
319
}
320
321
if (prev == nullptr) {
322
return nullptr; // tree empty
323
}
324
325
if (less(prev->value, p_value)) {
326
prev = prev->_next;
327
}
328
329
return prev;
330
}
331
332
void _insert_rb_fix(Element *p_new_node) {
333
Element *node = p_new_node;
334
Element *nparent = node->parent;
335
Element *ngrand_parent = nullptr;
336
337
while (nparent->color == RED) {
338
ngrand_parent = nparent->parent;
339
340
if (nparent == ngrand_parent->left) {
341
if (ngrand_parent->right->color == RED) {
342
_set_color(nparent, BLACK);
343
_set_color(ngrand_parent->right, BLACK);
344
_set_color(ngrand_parent, RED);
345
node = ngrand_parent;
346
nparent = node->parent;
347
} else {
348
if (node == nparent->right) {
349
_rotate_left(nparent);
350
node = nparent;
351
nparent = node->parent;
352
}
353
_set_color(nparent, BLACK);
354
_set_color(ngrand_parent, RED);
355
_rotate_right(ngrand_parent);
356
}
357
} else {
358
if (ngrand_parent->left->color == RED) {
359
_set_color(nparent, BLACK);
360
_set_color(ngrand_parent->left, BLACK);
361
_set_color(ngrand_parent, RED);
362
node = ngrand_parent;
363
nparent = node->parent;
364
} else {
365
if (node == nparent->left) {
366
_rotate_right(nparent);
367
node = nparent;
368
nparent = node->parent;
369
}
370
_set_color(nparent, BLACK);
371
_set_color(ngrand_parent, RED);
372
_rotate_left(ngrand_parent);
373
}
374
}
375
}
376
377
_set_color(_data._root->left, BLACK);
378
}
379
380
Element *_insert(const T &p_value) {
381
Element *new_parent = _data._root;
382
Element *node = _data._root->left;
383
C less;
384
385
while (node != _data._nil) {
386
new_parent = node;
387
388
if (less(p_value, node->value)) {
389
node = node->left;
390
} else if (less(node->value, p_value)) {
391
node = node->right;
392
} else {
393
return node; // Return existing node
394
}
395
}
396
397
Element *new_node = memnew_allocator(Element, A);
398
new_node->parent = new_parent;
399
new_node->right = _data._nil;
400
new_node->left = _data._nil;
401
new_node->value = p_value;
402
//new_node->data=_data;
403
404
if (new_parent == _data._root || less(p_value, new_parent->value)) {
405
new_parent->left = new_node;
406
} else {
407
new_parent->right = new_node;
408
}
409
410
new_node->_next = _successor(new_node);
411
new_node->_prev = _predecessor(new_node);
412
if (new_node->_next) {
413
new_node->_next->_prev = new_node;
414
}
415
if (new_node->_prev) {
416
new_node->_prev->_next = new_node;
417
}
418
419
_data.size_cache++;
420
_insert_rb_fix(new_node);
421
return new_node;
422
}
423
424
void _erase_fix_rb(Element *p_node) {
425
Element *root = _data._root->left;
426
Element *node = _data._nil;
427
Element *sibling = p_node;
428
Element *parent = sibling->parent;
429
430
while (node != root) { // If red node found, will exit at a break
431
if (sibling->color == RED) {
432
_set_color(sibling, BLACK);
433
_set_color(parent, RED);
434
if (sibling == parent->right) {
435
sibling = sibling->left;
436
_rotate_left(parent);
437
} else {
438
sibling = sibling->right;
439
_rotate_right(parent);
440
}
441
}
442
if ((sibling->left->color == BLACK) && (sibling->right->color == BLACK)) {
443
_set_color(sibling, RED);
444
if (parent->color == RED) {
445
_set_color(parent, BLACK);
446
break;
447
} else { // loop: haven't found any red nodes yet
448
node = parent;
449
parent = node->parent;
450
sibling = (node == parent->left) ? parent->right : parent->left;
451
}
452
} else {
453
if (sibling == parent->right) {
454
if (sibling->right->color == BLACK) {
455
_set_color(sibling->left, BLACK);
456
_set_color(sibling, RED);
457
_rotate_right(sibling);
458
sibling = sibling->parent;
459
}
460
_set_color(sibling, parent->color);
461
_set_color(parent, BLACK);
462
_set_color(sibling->right, BLACK);
463
_rotate_left(parent);
464
break;
465
} else {
466
if (sibling->left->color == BLACK) {
467
_set_color(sibling->right, BLACK);
468
_set_color(sibling, RED);
469
_rotate_left(sibling);
470
sibling = sibling->parent;
471
}
472
473
_set_color(sibling, parent->color);
474
_set_color(parent, BLACK);
475
_set_color(sibling->left, BLACK);
476
_rotate_right(parent);
477
break;
478
}
479
}
480
}
481
482
ERR_FAIL_COND(_data._nil->color != BLACK);
483
}
484
485
void _erase(Element *p_node) {
486
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
487
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
488
489
Element *sibling = nullptr;
490
if (rp == rp->parent->left) {
491
rp->parent->left = node;
492
sibling = rp->parent->right;
493
} else {
494
rp->parent->right = node;
495
sibling = rp->parent->left;
496
}
497
498
if (node->color == RED) {
499
node->parent = rp->parent;
500
_set_color(node, BLACK);
501
} else if (rp->color == BLACK && rp->parent != _data._root) {
502
_erase_fix_rb(sibling);
503
}
504
505
if (rp != p_node) {
506
ERR_FAIL_COND(rp == _data._nil);
507
508
rp->left = p_node->left;
509
rp->right = p_node->right;
510
rp->parent = p_node->parent;
511
rp->color = p_node->color;
512
if (p_node->left != _data._nil) {
513
p_node->left->parent = rp;
514
}
515
if (p_node->right != _data._nil) {
516
p_node->right->parent = rp;
517
}
518
519
if (p_node == p_node->parent->left) {
520
p_node->parent->left = rp;
521
} else {
522
p_node->parent->right = rp;
523
}
524
}
525
526
if (p_node->_next) {
527
p_node->_next->_prev = p_node->_prev;
528
}
529
if (p_node->_prev) {
530
p_node->_prev->_next = p_node->_next;
531
}
532
533
memdelete_allocator<Element, A>(p_node);
534
_data.size_cache--;
535
ERR_FAIL_COND(_data._nil->color == RED);
536
}
537
538
void _calculate_depth(Element *p_element, int &max_d, int d) const {
539
if (p_element == _data._nil) {
540
return;
541
}
542
543
_calculate_depth(p_element->left, max_d, d + 1);
544
_calculate_depth(p_element->right, max_d, d + 1);
545
546
if (d > max_d) {
547
max_d = d;
548
}
549
}
550
551
void _cleanup_tree(Element *p_element) {
552
if (p_element == _data._nil) {
553
return;
554
}
555
556
_cleanup_tree(p_element->left);
557
_cleanup_tree(p_element->right);
558
memdelete_allocator<Element, A>(p_element);
559
}
560
561
void _copy_from(const RBSet &p_set) {
562
clear();
563
// not the fastest way, but safeset to write.
564
for (Element *I = p_set.front(); I; I = I->next()) {
565
insert(I->get());
566
}
567
}
568
569
public:
570
const Element *find(const T &p_value) const {
571
if (!_data._root) {
572
return nullptr;
573
}
574
575
const Element *res = _find(p_value);
576
return res;
577
}
578
579
Element *find(const T &p_value) {
580
if (!_data._root) {
581
return nullptr;
582
}
583
584
Element *res = _find(p_value);
585
return res;
586
}
587
588
Element *lower_bound(const T &p_value) const {
589
if (!_data._root) {
590
return nullptr;
591
}
592
return _lower_bound(p_value);
593
}
594
595
bool has(const T &p_value) const {
596
return find(p_value) != nullptr;
597
}
598
599
Element *insert(const T &p_value) {
600
if (!_data._root) {
601
_data._create_root();
602
}
603
return _insert(p_value);
604
}
605
606
void erase(Element *p_element) {
607
if (!_data._root || !p_element) {
608
return;
609
}
610
611
_erase(p_element);
612
if (_data.size_cache == 0 && _data._root) {
613
_data._free_root();
614
}
615
}
616
617
bool erase(const T &p_value) {
618
if (!_data._root) {
619
return false;
620
}
621
622
Element *e = find(p_value);
623
if (!e) {
624
return false;
625
}
626
627
_erase(e);
628
if (_data.size_cache == 0 && _data._root) {
629
_data._free_root();
630
}
631
return true;
632
}
633
634
Element *front() const {
635
if (!_data._root) {
636
return nullptr;
637
}
638
639
Element *e = _data._root->left;
640
if (e == _data._nil) {
641
return nullptr;
642
}
643
644
while (e->left != _data._nil) {
645
e = e->left;
646
}
647
648
return e;
649
}
650
651
Element *back() const {
652
if (!_data._root) {
653
return nullptr;
654
}
655
656
Element *e = _data._root->left;
657
if (e == _data._nil) {
658
return nullptr;
659
}
660
661
while (e->right != _data._nil) {
662
e = e->right;
663
}
664
665
return e;
666
}
667
668
inline bool is_empty() const {
669
return _data.size_cache == 0;
670
}
671
inline int size() const {
672
return _data.size_cache;
673
}
674
675
int calculate_depth() const {
676
// used for debug mostly
677
if (!_data._root) {
678
return 0;
679
}
680
681
int max_d = 0;
682
_calculate_depth(_data._root->left, max_d, 0);
683
return max_d;
684
}
685
686
void clear() {
687
if (!_data._root) {
688
return;
689
}
690
691
_cleanup_tree(_data._root->left);
692
_data._root->left = _data._nil;
693
_data.size_cache = 0;
694
_data._free_root();
695
}
696
697
void operator=(const RBSet &p_set) {
698
_copy_from(p_set);
699
}
700
701
RBSet(const RBSet &p_set) {
702
_copy_from(p_set);
703
}
704
705
RBSet(std::initializer_list<T> p_init) {
706
for (const T &E : p_init) {
707
insert(E);
708
}
709
}
710
711
_FORCE_INLINE_ RBSet() {}
712
713
~RBSet() {
714
clear();
715
}
716
};
717
718