1
+ #include < cstdlib>
2
+ #include < ctime>
1
3
#include < iostream>
2
4
#include < set>
5
+ #include < unordered_set>
3
6
#include < utility>
4
7
using namespace std ;
5
8
6
9
// TODO: smuggle color in least significant bit of pointers because pointers
7
10
// are always even on most platforms
8
11
9
- // TODO: implement delete
10
-
11
- // TODO: implement rebalancing in insert_fix
12
+ // TODO: implement rebalancing
12
13
13
14
template <typename T>
14
15
class rb_tree_t {
15
16
public:
16
- rb_tree_t () : root(nullptr ) {}
17
+ rb_tree_t () : root(nullptr ), count( 0 ) {}
17
18
void insert (const T& t) { insert (root, t); }
18
- bool find (const T& t) { return find (nullptr , root, t).found ; }
19
+ bool exists (const T& t) { return find (nullptr , root, t).found ; }
20
+ void remove (const T& t) { remove (root, t); }
21
+ size_t max_height () { return max_height (root); }
22
+ size_t size () { return count; }
23
+ size_t size_traversal () { return size_traversal (root); }
19
24
20
25
private:
21
26
enum color_t {RED, BLACK};
@@ -44,11 +49,88 @@ class rb_tree_t {
44
49
return find (node, node->right , t);
45
50
}
46
51
}
47
-
52
+
53
+ search_t find (node_t * node, const T& t) {
54
+ node_t * parent = node ? node->parent : nullptr ;
55
+ return find (parent, node, t);
56
+ }
57
+
58
+ // Rotations are untested
59
+ void rotate_left (node_t * node) {
60
+ if (!node) {
61
+ return ;
62
+ }
63
+
64
+ // establish right link
65
+ node_t * old_right = node->right ;
66
+ if (old_right) {
67
+ node->right = old_right->left ;
68
+ if (old_right->left ) {
69
+ old_right->left ->parent = node;
70
+ }
71
+ }
72
+
73
+ // establish new parent for old right
74
+ if (old_right) {
75
+ old_right->parent = node->parent ;
76
+ }
77
+ if (node->parent ) {
78
+ if (node == node->parent ->left ) {
79
+ node->parent ->left = old_right;
80
+ } else {
81
+ node->parent ->right = old_right;
82
+ }
83
+ } else {
84
+ root = old_right;
85
+ }
86
+
87
+ // link node and old right
88
+ if (old_right) {
89
+ old_right->left = node;
90
+ }
91
+ node->parent = old_right;
92
+ }
93
+
94
+ void rotate_right (node_t * node) {
95
+ if (!node) {
96
+ return ;
97
+ }
98
+
99
+ node_t * old_left = node->left ;
100
+
101
+ // establish left link
102
+ if (old_left) {
103
+ node->left = old_left->right ;
104
+ if (old_left->right ) {
105
+ old_left->right ->parent = node;
106
+ }
107
+ }
108
+
109
+ // establish new parent for old left
110
+ if (old_left) {
111
+ old_left->parent = node->parent ;
112
+ }
113
+ if (node->parent ) {
114
+ if (node == node->parent ->right ) {
115
+ node->parent ->right = old_left;
116
+ } else {
117
+ node->parent ->left = old_left;
118
+ }
119
+ } else {
120
+ root = old_left;
121
+ }
122
+
123
+ // link node and old left
124
+ if (old_left) {
125
+ old_left->right = node;
126
+ }
127
+ node->parent = old_left;
128
+ }
129
+
48
130
void insert_fixup (node_t * node) { }
49
131
50
132
void insert (node_t * node, const T& t) {
51
- auto search = find (nullptr , node, t);
133
+ auto search = find (node, t);
52
134
if (!search.found ) {
53
135
node_t * parent = search.insert ;
54
136
node_t * newnode = new node_t ;
@@ -67,24 +149,142 @@ class rb_tree_t {
67
149
root = newnode;
68
150
}
69
151
insert_fixup (newnode);
152
+ count++;
70
153
}
71
154
}
72
155
156
+ void remove_fixup (node_t * node) {
157
+ if (node->color != BLACK) { // is this really needed?
158
+ return ;
159
+ }
160
+ }
161
+
162
+ void remove (node_t * match) {
163
+ if (!match) {
164
+ return ;
165
+ }
166
+ node_t * parent = match->parent ;
167
+
168
+ if (match->left == nullptr
169
+ && match->right == nullptr ) { // no children, so delete
170
+ if (parent) {
171
+ if (match == parent->left ) {
172
+ parent->left = nullptr ;
173
+ } else {
174
+ parent->right = nullptr ;
175
+ }
176
+ } else {
177
+ root = nullptr ;
178
+ }
179
+ delete match;
180
+ } else if (match->left == nullptr
181
+ && match->right != nullptr ) { // one child, link parent to right
182
+ if (parent) {
183
+ if (match == parent->left ) {
184
+ parent->left = match->right ;
185
+ } else {
186
+ parent->right = match->right ;
187
+ }
188
+ match->right ->parent = parent;
189
+ } else {
190
+ root = match->right ;
191
+ root->parent = nullptr ;
192
+ }
193
+ delete match;
194
+ } else if (match->left != nullptr
195
+ && match->right == nullptr ) { // one child, link parent to left
196
+ if (parent) {
197
+ if (match == parent->left ) {
198
+ parent->left = match->left ;
199
+ } else {
200
+ parent->right = match->left ;
201
+ }
202
+ match->left ->parent = parent;
203
+ } else {
204
+ root = match->left ;
205
+ root->parent = nullptr ;
206
+ }
207
+ delete match;
208
+ } else { // two children
209
+ // find smallest node larger than match
210
+ node_t * successor = match->right ;
211
+ while (successor->left ) {
212
+ successor = successor->left ;
213
+ }
214
+
215
+ // place successor value into match and remove successor from tree
216
+ match->t = successor->t ;
217
+ remove (successor);
218
+ }
219
+ }
220
+
221
+ void remove (node_t * node, const T& t) {
222
+ auto search = find (node, t);
223
+ if (!search.found ) {
224
+ return ;
225
+ }
226
+ remove (search.insert );
227
+ count--;
228
+ }
229
+
230
+ size_t max_height (node_t * node) {
231
+ if (!node) {
232
+ return 0 ;
233
+ }
234
+
235
+ size_t local_max = max_height (node->left );
236
+ local_max = max (max_height (node->right ), local_max);
237
+ local_max++;
238
+ return local_max;
239
+ }
240
+
241
+ size_t size_traversal (node_t * node) {
242
+ if (!node) {
243
+ return 0 ;
244
+ }
245
+
246
+ size_t size = size_traversal (node->left ) + size_traversal (node->right );
247
+ size++; // for this node
248
+ return size;
249
+ }
250
+
73
251
node_t * root;
252
+ size_t count;
74
253
};
75
254
76
255
int main () {
256
+ srand (time (NULL ));
257
+ unordered_set<int > data; // random order traversal
77
258
set<int > a;
78
259
rb_tree_t <int > b;
79
- auto data = {5 , 3 , 4 , 2 , 1 , 7 , 6 , 9 , 8 , 10 };
260
+ const auto SIZE = 1 + (rand () % (1024 * 10 ));
261
+ cout << " SIZE = " << SIZE << endl;
262
+ for (int i = 0 ; i < SIZE; i++) {
263
+ data.insert (rand ());
264
+ }
265
+ auto check_size = [&b]() {
266
+ if (b.size () != b.size_traversal ()) {
267
+ cout << " SIZE mismatch" << b.size () << " != (traversal) "
268
+ << b.size_traversal () << endl;
269
+ }
270
+ };
80
271
for (auto t : data) {
81
272
a.insert (t);
82
273
b.insert (t);
274
+ check_size ();
83
275
}
84
276
for (auto t : data) {
85
- if (!b.find (t)) {
277
+ if (!b.exists (t)) {
86
278
cout << " NOT FOUND" << endl;
87
279
}
88
280
}
281
+ cout << " MAX HEIGHT = " << b.max_height () << endl;
282
+ for (auto t : data) {
283
+ b.remove (t);
284
+ check_size ();
285
+ if (b.exists (t)) {
286
+ cout << " FOUND WHEN ALREADY DELETED" << endl;
287
+ }
288
+ }
89
289
return 0 ;
90
290
}
0 commit comments