-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRBTree.cpp
342 lines (315 loc) · 10.7 KB
/
RBTree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/*!
* Constructor
*/
RBTree::RBTree() {
root = nullptr;
}
/*!
*To search a given key in Binary Search Tree, we first compare it with root,
* if the key is present at root, we return root. If key is greater than root’s key,
* we recur for right subtree of root node. Otherwise we recur for left subtree.
* @param root Root node of RBT
* @param building_num Node to be searched for
* @return Return the searched node
*/
Node *search(Node *root, int building_num) {
if (root == nullptr)
return nullptr;
else if (root->building_num == building_num)
return root;
else if (building_num < root->building_num)
return ::search(root->left, building_num);
else
return ::search(root->right, building_num);
}
/*!
* https://www.geeksforgeeks.org/count-bst-nodes-that-are-in-a-given-range/
* The idea is to traverse the given binary search tree starting from root.
* For every node being visited, check if this node lies in range, if yes,
* then print to file and recur for both of its children. If current node
* is smaller than low value of range, then recur for right child, else recur for left child.
* @param root Root of tree
* @param low Lowest integer value to look up
* @param high Highest integer value to look up
*/
void inorder(Node *root, int low, int high, std::vector <std::string> &res) {
if (root == nullptr) {
return;
}
if (root->building_num > low) {
::inorder(root->left, low, high, res);
}
if (root->building_num <= high && root->building_num >= low) {
Building *correspondingBuilding = root->twin;
std::stringstream ss;
ss << "(" << correspondingBuilding->building_num << "," << correspondingBuilding->executed_time << ","
<< correspondingBuilding->total_time << ")";
res.push_back(ss.str());
}
if (root->building_num < high) {
::inorder(root->right, low, high, res);
}
}
/*!
* Helper function that perform search for a node in RBTree and prints it.
* @param building_num Building to be searched for
* @return Searched node with building_num
*/
Node *RBTree::search(int building_num) {
Node *found = ::search(root, building_num);
if (found == nullptr)
fout << "(0,0,0)\n";
else {
Building *correspondingBuilding = found->twin;
fout << "(" << correspondingBuilding->building_num << "," << correspondingBuilding->executed_time << ","
<< correspondingBuilding->total_time << ")" << "\n";
}
return found;
}
/*!
* https://www.geeksforgeeks.org/c-program-red-black-tree-insertion/
* Insets a given node in red black tree. If the node to be inserted already exists in the red black, throws
* error and half the execution of current program
* @param root Root Node of Tree
* @param ptr Node to be inserted
* @return Inserted element
*/
Node *insert(Node *root, Node *ptr) {
if (root == nullptr)
return ptr;
if (ptr->building_num < root->building_num) {
root->left = insert(root->left, ptr);
root->left->parent = root;
} else if (ptr->building_num > root->building_num) {
root->right = insert(root->right, ptr);
root->right->parent = root;
} else {
std::cerr << "Duplicate Building Number" << "\n";
exit(1);
}
return root;
}
/*!
* Helper method insert a given building in red black tree. After insertion, fixes any violation in red black tree.
*
* @param building_num: Building number of the node to be inserted
* @return Returns the inserted node in red black tree
*/
Node *RBTree::insert(const int &building_num) {
Node *node = new Node(building_num);
Node *res = node;
root = ::insert(root, node);
fix(node);
return res;
}
/*!
* Helper method to print the building triplets from red black tree.
* @param low: lowest building number to be printed
* @param high: highest building number to be printed
*/
void RBTree::inorder(int low, int high) {
std::vector <std::string> res;
::inorder(root, low, high, res);
std::sort(res.begin(), res.end());
std::string s;
for (size_t i = 0; i < res.size(); ++i) {
s += res[i];
s += ",";
}
s.pop_back();
fout << s;
fout << "\n";
}
/*!
* Returns the successor node in case an element is deleted from red black tree
* @param node: Node to find successor of
* @return returns: If found returns pointer reference to the successor node else returns nullptrt
*/
Node *successor(Node *node) {
Node *successor = nullptr;
if (node->left != nullptr) {
successor = node->left;
while (successor->right != nullptr)
successor = successor->right;
} else {
successor = node->right;
while (successor->left != nullptr) {
successor = successor->left;
}
}
return successor;
}
/*!
* https://github.com/greatsharma/Red_Black_Tree/blob/master/RB_Tree.cpp
* Deletes a specified node from red black tre
* @param z: Node to be deleted from the red black tree.
*/
void RBTree::delete_node(Node *node) {
node = root;
Node *pVoid = nullptr;
Node *node_to_be_deleted = nullptr;
Node *child = nullptr;
/*
node :- node which the user wants to delete
node_to_be_deleted :- node which is actually deleted
child :- node_to_be_deleted's child
*/
if (node->left == nullptr || node->right == nullptr)
node_to_be_deleted = node;
else
node_to_be_deleted = successor(node);
if (node_to_be_deleted->left != nullptr)
child = node_to_be_deleted->left;
else {
if (node_to_be_deleted->right != nullptr)
child = node_to_be_deleted->right;
else
child = nullptr;
}
if (child != nullptr)
child->parent = node_to_be_deleted->parent;
if (node_to_be_deleted->parent == nullptr)
root = child;
else {
if (node_to_be_deleted == node_to_be_deleted->parent->left)
node_to_be_deleted->parent->left = child;
else
node_to_be_deleted->parent->right = child;
}
if (node_to_be_deleted != node) {
node->color = node_to_be_deleted->color;
node->building_num = node_to_be_deleted->building_num;
node->twin = node_to_be_deleted->twin;
struct Building *temp;
temp = node->twin;
temp->twin = node;
}
if (pVoid != nullptr)
fix(child);
}
/*!
* Performs a left rotation on red black tree
* @param node
*/
void RBTree::left_rotate(Node *node) {
if (node->right == nullptr) {
return;
} else {
Node *right_child = node->right;
if (right_child->left != nullptr) {
node->right = right_child->left;
right_child->left->parent = node;
} else {
node->right = nullptr;
}
if (node->parent != nullptr) right_child->parent = node->parent;
if (node->parent == nullptr) root = right_child;
else if (node == node->parent->left) node->parent->left = right_child;
else node->parent->right = right_child;
right_child->left = node;
node->parent = right_child;
}
}
/*!
* Performs a right rotation on red black tree
* @param node
*/
void RBTree::right_rotate(Node *node) {
if (node->left == nullptr)
return;
else {
Node *y = node->left;
if (y->right != nullptr) {
node->left = y->right;
y->right->parent = node;
} else
node->left = nullptr;
if (node->parent != nullptr)
y->parent = node->parent;
if (node->parent == nullptr)
root = y;
else {
if (node == node->parent->left)
node->parent->left = y;
else
node->parent->right = y;
}
y->right = node;
node->parent = y;
}
}
/*!
* Fixes red black tree, in case of violation either due to insertion or deletion of any node in red black tree
* @param node: Node that caused violation
*/
void RBTree::fix(Node *&node) {
Node *sibling; // node's sibling
while (node != root && node->color == BLACK) {
if (node->parent->left == node) {
sibling = node->parent->right;
if (sibling->color == RED) {
/*
case 1 :- sibling is RED
conclusion :- Always take control to case 2,3 or 4.
*/
sibling->color = BLACK;
node->parent->color = RED;
RBTree::left_rotate(node->parent);
sibling = node->parent->right;
}
if (sibling->right->color == BLACK && sibling->left->color == BLACK) {
/*
case 2 :- sibling and both it's children are BLACK.
solution :- take BLACK from both node and sibling.
conclusion :- terminates if came from case 1
*/
sibling->color = RED;
node = node->parent;
} else if (sibling->right->color == BLACK) {
/*
case 3 :- sibling=BLACK , sibling->left=RED and sibling->right=BLACK
conclusion :- case 3 take us to case 4
*/
sibling->left->color = BLACK;
sibling->color = RED;
RBTree::right_rotate(sibling);
sibling = node->parent->right;
} else {
/*
case 4 :- sibling is BLACK and sibling->right is RED
conclusion :- terminates
*/
sibling->color = node->parent->color;
node->parent->color = BLACK;
sibling->right->color = BLACK;
RBTree::left_rotate(node->parent);
node = root;
}
} else {
sibling = node->parent->left;
if (sibling->color == RED) {
sibling->color = BLACK;
node->parent->color = RED;
right_rotate(node->parent);
sibling = node->parent->left;
}
if (sibling->left->color == BLACK && sibling->right->color == BLACK) {
sibling->color = RED;
node = node->parent;
} else if (sibling->left->color == BLACK) {
sibling->right->color = BLACK;
sibling->color = RED;
left_rotate(sibling);
sibling = node->parent->left;
} else {
sibling->color = node->parent->color;
node->parent->color = BLACK;
sibling->left->color = BLACK;
right_rotate(node->parent);
node = root;
}
}
node->color = BLACK;
root->color = BLACK;
}
}