Skip to content

Commit 66526f7

Browse files
committed
Red black tree: deletions working and tested
Rotations to be tested and fixing coloring to be implemented and tested
1 parent 42ac331 commit 66526f7

File tree

1 file changed

+209
-9
lines changed

1 file changed

+209
-9
lines changed

data_structures/red_black_tree/red_black_tree.cpp

Lines changed: 209 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1+
#include <cstdlib>
2+
#include <ctime>
13
#include <iostream>
24
#include <set>
5+
#include <unordered_set>
36
#include <utility>
47
using namespace std;
58

69
// TODO: smuggle color in least significant bit of pointers because pointers
710
// are always even on most platforms
811

9-
// TODO: implement delete
10-
11-
// TODO: implement rebalancing in insert_fix
12+
// TODO: implement rebalancing
1213

1314
template <typename T>
1415
class rb_tree_t {
1516
public:
16-
rb_tree_t() : root(nullptr) {}
17+
rb_tree_t() : root(nullptr), count(0) {}
1718
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); }
1924

2025
private:
2126
enum color_t {RED, BLACK};
@@ -44,11 +49,88 @@ class rb_tree_t {
4449
return find(node, node->right, t);
4550
}
4651
}
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+
48130
void insert_fixup(node_t* node) { }
49131

50132
void insert(node_t* node, const T& t) {
51-
auto search = find(nullptr, node, t);
133+
auto search = find(node, t);
52134
if (!search.found) {
53135
node_t* parent = search.insert;
54136
node_t* newnode = new node_t;
@@ -67,24 +149,142 @@ class rb_tree_t {
67149
root = newnode;
68150
}
69151
insert_fixup(newnode);
152+
count++;
70153
}
71154
}
72155

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+
73251
node_t* root;
252+
size_t count;
74253
};
75254

76255
int main() {
256+
srand(time(NULL));
257+
unordered_set<int> data; // random order traversal
77258
set<int> a;
78259
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+
};
80271
for (auto t : data) {
81272
a.insert(t);
82273
b.insert(t);
274+
check_size();
83275
}
84276
for (auto t : data) {
85-
if (!b.find(t)) {
277+
if (!b.exists(t)) {
86278
cout << "NOT FOUND" << endl;
87279
}
88280
}
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+
}
89289
return 0;
90290
}

0 commit comments

Comments
 (0)