yfast 0.6.1
Loading...
Searching...
No Matches
avl.h
1#ifndef _YFAST_IMPL_AVL_H
2#define _YFAST_IMPL_AVL_H
3
4#include <functional>
5
6#include <yfast/impl/bst.h>
7
8namespace yfast::impl {
9
15template <typename Node, typename Compare = std::less<typename Node::Key>>
16class AVL: public BST<Node, Compare> {
17public:
18 using typename BST<Node, Compare>::Key;
19
20 typedef struct {
21 AVL left;
22 AVL right;
23 Node* left_max;
25
26protected:
27 using BST<Node, Compare>::_cmp;
28 using BST<Node, Compare>::_root;
29
30public:
31 explicit AVL(Compare cmp = Compare()): AVL(nullptr, cmp) {}
32 AVL(const AVL& other) = delete;
33 AVL(AVL&& other) noexcept: BST<Node, Compare>(std::move(other)) {}
34
35 [[nodiscard]] unsigned int height() const { return height(_root); }
36
42 Node* insert(Node* node) {
43 auto replaced = this->template BST<Node, Compare>::insert(node);
44 if (replaced != nullptr) {
45 if (replaced->is_left_heavy()) {
46 node->set_left_heavy();
47 }
48 else if (replaced->is_right_heavy()) {
49 node->set_right_heavy();
50 }
51 else {
52 node->set_balanced();
53 }
54 return replaced;
55 }
56 node->set_balanced();
57 for (auto probe = node; probe != nullptr; probe = probe->parent) {
58 auto parent = probe->parent;
59 if (parent == nullptr) {
60 break;
61 }
62 auto grand_parent = parent->parent;
63 Node* new_subroot;
64 if (probe == parent->left()) {
65 if (parent->is_left_heavy()) {
66 if (probe->is_right_heavy()) {
67 new_subroot = rotate_left_right(parent, probe);
68 }
69 else {
70 new_subroot = rotate_right(parent, probe);
71 }
72 }
73 else {
74 if (parent->is_right_heavy()) {
75 parent->set_balanced();
76 break;
77 }
78 else {
79 parent->set_left_heavy();
80 continue;
81 }
82 }
83 }
84 else {
85 if (parent->is_right_heavy()) {
86 if (probe->is_left_heavy()) {
87 new_subroot = rotate_right_left(parent, probe);
88 }
89 else {
90 new_subroot = rotate_left(parent, probe);
91 }
92 }
93 else {
94 if (parent->is_left_heavy()) {
95 parent->set_balanced();
96 break;
97 }
98 else {
99 parent->set_right_heavy();
100 continue;
101 }
102 }
103 }
104 if (grand_parent != nullptr) {
105 if (parent == grand_parent->left()) {
106 link_left(grand_parent, new_subroot);
107 }
108 else {
109 link_right(grand_parent, new_subroot);
110 }
111 }
112 else {
113 new_subroot->parent = nullptr;
114 _root = new_subroot;
115 }
116 break;
117 }
118 return nullptr;
119 }
120
121 Node* remove(Node* node) {
122 auto remove_report = this->template BST<Node, Compare>::remove(node);
123 auto substitution = remove_report.substitution;
124 auto new_subroot = remove_report.subtree_child;
125 auto parent = remove_report.subtree_parent;
126 bool is_left_child = remove_report.is_left_child;
127
128 if (substitution != new_subroot) {
129 if (node->is_left_heavy()) {
130 substitution->set_left_heavy();
131 }
132 else if (node->is_right_heavy()) {
133 substitution->set_right_heavy();
134 }
135 else {
136 substitution->set_balanced();
137 }
138 }
139
140 while (parent != nullptr) {
141 bool sibling_balanced;
142 auto grand_parent = parent->parent;
143 if (is_left_child) {
144 auto sibling = parent->right();
145 if (parent->is_right_heavy()) {
146 sibling_balanced = sibling->is_balanced();
147 if (sibling->is_left_heavy()) {
148 new_subroot = rotate_right_left(parent, sibling);
149 }
150 else {
151 new_subroot = rotate_left(parent, sibling);
152 }
153 }
154 else {
155 if (parent->is_balanced()) {
156 parent->set_right_heavy();
157 break;
158 }
159 new_subroot = parent;
160 new_subroot->set_balanced();
161 parent = grand_parent;
162 if (parent != nullptr) {
163 is_left_child = (new_subroot == parent->left());
164 }
165 continue;
166 }
167 }
168 else {
169 auto sibling = parent->left();
170 if (parent->is_left_heavy()) {
171 sibling_balanced = sibling->is_balanced();
172 if (sibling->is_right_heavy()) {
173 new_subroot = rotate_left_right(parent, sibling);
174 }
175 else {
176 new_subroot = rotate_right(parent, sibling);
177 }
178 }
179 else {
180 if (parent->is_balanced()) {
181 parent->set_left_heavy();
182 break;
183 }
184 new_subroot = parent;
185 new_subroot->set_balanced();
186 parent = grand_parent;
187 if (parent != nullptr) {
188 is_left_child = (new_subroot == parent->left());
189 }
190 continue;
191 }
192 }
193 if (grand_parent != nullptr) {
194 if (parent == grand_parent->left()) {
195 link_left(grand_parent, new_subroot);
196 is_left_child = true;
197 }
198 else {
199 link_right(grand_parent, new_subroot);
200 is_left_child = false;
201 }
202 }
203 else {
204 new_subroot->parent = nullptr;
205 _root = new_subroot;
206 }
207 if (sibling_balanced) {
208 break;
209 }
210 parent = grand_parent;
211 }
212 return node;
213 }
214
215 SplitResult split() { // TODO: split by specified node
216 if (_root == nullptr) {
217 return { AVL(_cmp), AVL(_cmp), nullptr };
218 }
219
220 SplitResult split_result { AVL(_root->left(), _cmp), AVL(_root->right(), _cmp), _root };
221 split_result.left.insert(_root);
222
223 _root = nullptr;
224
225 return split_result;
226 }
227
228 static AVL merge(AVL&& subtree1, AVL&& subtree2) {
229 auto first_is_less = subtree1._cmp(subtree1._root->key, subtree2._root->key);
230 auto& left = first_is_less ? subtree1 : subtree2;
231 auto& right = first_is_less ? subtree2 : subtree1;
232 auto new_subroot = AVL::_leftmost(right._root);
233 right.remove(new_subroot);
234 new_subroot->parent = nullptr;
235 const auto left_height = left.height();
236 const auto right_height = right.height();
237 if (left_height > right_height + 1) {
238 auto probe = _rightmost(left._root);
239 int probe_height = height(probe);
240 while (probe_height < right_height) {
241 probe = probe->parent;
242 if (probe->is_left_heavy()) {
243 probe_height += 2;
244 }
245 else {
246 ++probe_height;
247 }
248 }
249
250 auto parent = probe->parent;
251 link_left(new_subroot, probe);
252 link_right(new_subroot, right._root);
253 link_right(parent, new_subroot);
254 update_size_path(new_subroot);
255 if (right_height > probe_height) {
256 new_subroot->set_right_heavy();
257 }
258 else if (right_height < probe_height) {
259 new_subroot->set_left_heavy();
260 }
261 else {
262 new_subroot->set_balanced();
263 }
264
265 while (parent != nullptr) {
266 auto grand_parent = parent->parent;
267 if (parent->is_right_heavy()) {
268 if (new_subroot->is_left_heavy()) {
269 auto node = rotate_right_left(parent, new_subroot);
270 if (grand_parent != nullptr) {
271 link_right(grand_parent, node);
272 }
273 else {
274 node->parent = nullptr;
275 left._root = node;
276 }
277 break; // subroot is not balanced
278 }
279 else {
280 auto node = rotate_left(parent, new_subroot);
281 if (grand_parent != nullptr) {
282 link_right(grand_parent, node);
283 }
284 else {
285 node->parent = nullptr;
286 left._root = node;
287 }
288 if (node->is_balanced()) {
289 break;
290 }
291 // new_subroot = node; // redundant
292 parent = grand_parent;
293 }
294 }
295 else {
296 if (parent->is_left_heavy()) {
297 parent->set_balanced();
298 break;
299 }
300 parent->set_right_heavy();
301 new_subroot = parent;
302 parent = grand_parent;
303 }
304 }
305
306 right._root = nullptr;
307 return std::move(left);
308 }
309 if (right_height > left_height + 1) {
310 auto probe = _leftmost(right._root);
311 int probe_height = height(probe);
312 while (probe_height < left_height) {
313 probe = probe->parent;
314 if (probe->is_right_heavy()) {
315 probe_height += 2;
316 }
317 else {
318 ++probe_height;
319 }
320 }
321
322 auto parent = probe->parent;
323 link_left(new_subroot, left._root);
324 link_right(new_subroot, probe);
325 link_left(parent, new_subroot);
326 update_size_path(new_subroot);
327 if (probe_height < left_height) {
328 new_subroot->set_left_heavy();
329 }
330 else if (probe_height > left_height) {
331 new_subroot->set_right_heavy();
332 }
333 else {
334 new_subroot->set_balanced();
335 }
336
337 while (parent != nullptr) {
338 auto grand_parent = parent->parent;
339 if (parent->is_left_heavy()) {
340 if (new_subroot->is_right_heavy()) {
341 auto node = rotate_left_right(parent, new_subroot);
342 if (grand_parent != nullptr) {
343 link_left(grand_parent, node);
344 }
345 else {
346 node->parent = nullptr;
347 right._root = node;
348 }
349 break; // subroot is not balanced
350 }
351 else {
352 auto node = rotate_right(parent, new_subroot);
353 if (grand_parent != nullptr) {
354 link_left(grand_parent, node);
355 }
356 else {
357 node->parent = nullptr;
358 right._root = node;
359 }
360 if (node->is_balanced()) {
361 break;
362 }
363 // new_subroot = node; // redundant
364 parent = grand_parent;
365 }
366 }
367 else {
368 if (parent->is_right_heavy()) {
369 parent->set_balanced();
370 break;
371 }
372 parent->set_left_heavy();
373 new_subroot = parent;
374 parent = grand_parent;
375 }
376 }
377
378 left._root = nullptr;
379 return std::move(right);
380 }
381
382 link_left(new_subroot, left._root);
383 link_right(new_subroot, right._root);
384 update_size(new_subroot);
385 if (left_height > right_height) {
386 new_subroot->set_left_heavy();
387 }
388 else if (right_height > left_height) {
389 new_subroot->set_right_heavy();
390 }
391 else {
392 new_subroot->set_balanced();
393 }
394 left._root = nullptr;
395 right._root = nullptr;
396 return AVL(new_subroot, left._cmp);
397 }
398
399protected:
400 explicit AVL(Node* root, Compare cmp = Compare()): BST<Node, Compare>(root, cmp) {}
401
402 using BST<Node, Compare>::link_left;
403 using BST<Node, Compare>::link_right;
404 using BST<Node, Compare>::update_size;
405 using BST<Node, Compare>::update_size_path;
406 using BST<Node, Compare>::_leftmost;
407 using BST<Node, Compare>::_rightmost;
408
409private:
410 static unsigned int height(const Node* node) {
411 if (node == nullptr) {
412 return 0;
413 }
414 if (node->is_right_heavy()) {
415 return 2 + height(node->left());
416 }
417 if (node->is_left_heavy()) {
418 return 2 + height(node->right());
419 }
420 return 1 + height(node->right());
421 }
422
423 static Node* rotate_left(Node* parent, Node* child) {
424 link_right(parent, child->left());
425 link_left(child, parent);
426
427 update_size(parent);
428 update_size(child);
429
430 if (child->is_balanced()) {
431 parent->set_right_heavy();
432 child->set_left_heavy();
433 }
434 else {
435 parent->set_balanced();
436 child->set_balanced();
437 }
438
439 return child;
440 }
441
442 static Node* rotate_right(Node* parent, Node* child) {
443 link_left(parent, child->right());
444 link_right(child, parent);
445
446 update_size(parent);
447 update_size(child);
448
449 if (child->is_balanced()) {
450 parent->set_left_heavy();
451 child->set_right_heavy();
452 }
453 else {
454 parent->set_balanced();
455 child->set_balanced();
456 }
457
458 return child;
459 }
460
461 static Node* rotate_right_left(Node* parent, Node* child) {
462 auto grand_child = child->left();
463
464 link_left(child, grand_child->right());
465 link_right(grand_child, child);
466 link_right(parent, grand_child->left());
467 link_left(grand_child, parent);
468
469 update_size(parent);
470 update_size(child);
471 update_size(grand_child);
472
473 if (grand_child->is_balanced()) {
474 parent->set_balanced();
475 child->set_balanced();
476 }
477 else if (grand_child->is_right_heavy()) {
478 parent->set_left_heavy();
479 child->set_balanced();
480 }
481 else {
482 parent->set_balanced();
483 child->set_right_heavy();
484 }
485 grand_child->set_balanced();
486
487 return grand_child;
488 }
489
490 static Node* rotate_left_right(Node* parent, Node* child) {
491 auto grand_child = child->right();
492
493 link_right(child, grand_child->left());
494 link_left(grand_child, child);
495 link_left(parent, grand_child->right());
496 link_right(grand_child, parent);
497
498 update_size(parent);
499 update_size(child);
500 update_size(grand_child);
501
502 if (grand_child->is_balanced()) {
503 parent->set_balanced();
504 child->set_balanced();
505 }
506 else if (grand_child->is_right_heavy()) {
507 parent->set_balanced();
508 child->set_left_heavy();
509 }
510 else {
511 parent->set_right_heavy();
512 child->set_balanced();
513 }
514 grand_child->set_balanced();
515
516 return grand_child;
517 }
518};
519
520}
521
522#endif
Definition avl.h:16
Node * insert(Node *node)
Definition avl.h:42
Definition bst.h:14
Node * insert(Node *node)
Definition bst.h:92