2// by Sergey Troshin, 27 March 2017.
3// With thankfulness to https://youtu.be/UaLIHuR1t8Q
4// But if smb would watch it
5// in DELETION video in case 5 parent can be both red and black, not just black.
28 node * parent = nullptr;
30 return parent == nullptr;
33 node(const T& val, color cl) : val(val), cl(cl) {}
34 node(const T& val, color cl, node* parent) : val(val), cl(cl), parent(parent) {}
35 node(T&& val, color cl) : val(val), cl(cl) {}
36 node(T&& val, color cl, node* parent) : val(val), cl(cl), parent(parent) {}
48 node * root = nullptr;
49 node * sibling(node * me) {
50 if (me == nullptr || me->is_root()) return nullptr;
51 node * a = me->parent->lch;
52 node * b = me->parent->rch;
53 return (a == me ? b : a);
55 bool is_sibling_red(node * me) { // case 1
56 node * sib = sibling(me);
57 if (sib == nullptr) return 0;
58 return sib->cl == RED;
60 /**********************************************************************************
61 * if we find that we are red and our parent is red - *
62 * we should make some rotation in some cases *
63 * rotate(cur) basically suppose that cur is red and cur's parent is red *
64 **********************************************************************************/
65 void right_rotate(node * me, bool change_color) { // we are left child, so rotate our parent on positive angel
66 if (me->parent == root)
68 node * parent = me->parent;
69 me->parent = parent->parent;
70 if (parent->parent != nullptr) {
71 if (parent->parent->lch == parent)
72 parent->parent->lch = me;
74 parent->parent->rch = me;
76 parent->lch = me->rch;
77 if (me->rch != nullptr)
78 me->rch->parent = parent;
87 void left_rotate(node * me, bool change_color) { // we are right child
88 if (me->parent == root)
90 node * parent = me->parent;
91 me->parent = parent->parent; // me-to-grdad
92 if (parent->parent != nullptr) {
93 if (parent->parent->lch == parent)
94 parent->parent->lch = me; //grdad-to-me
96 parent->parent->rch = me;
98 parent->rch = me->lch;
99 if (me->lch != nullptr)
100 me->lch->parent = parent;
109 // calculate max black sum in subtree recursively
110 size_t black_sum(node * cur) {
113 size_t ans = std::max(black_sum(cur->lch), black_sum(cur->rch));
114 if (cur->cl == BLACK)
119 // check red-black invariant recursively
120 bool is_tree_red_black(node * cur) {
125 // red-red relationship
126 if (get_color(cur) == RED && (get_color(cur->lch) == RED || get_color(cur->rch) == RED))
128 return (black_sum(cur->lch) == black_sum(cur->rch)
129 && is_tree_red_black(cur->lch) && is_tree_red_black(cur->rch));
131 /********************************************************
132 * main function that repair invariant *
133 * it's fast and do constant number of rotations at all *
134 ********************************************************/
135 void check(node * cur) {
136 if (cur->parent == nullptr || cur->parent->cl == BLACK) {
139 if (cur->parent->parent == nullptr) {
140 cur->parent->cl = BLACK;
143 // so we are red, and our parent too
144 if (is_sibling_red(cur->parent)) {
145 node * sib = sibling(cur->parent);
146 cur->parent->cl = BLACK;
148 node * grand_dad = cur->parent->parent;
149 if (!grand_dad->is_root()) {
157 // now we face 4 cases
158 // LR means that we cur(red) is Left child and cur's parent(red too) is Right child
159 if (cur->parent->parent->lch == cur->parent && cur->parent->rch == cur) { // LR
162 } else if (cur->parent->parent->rch == cur->parent && cur->parent->lch == cur) {// RL
163 right_rotate(cur, 0);
166 // only LL or RR ve have now. There we go.
167 if (cur->parent->parent->lch == cur->parent && cur->parent->lch == cur) { // LL
168 right_rotate(cur->parent, 1);
169 } else if (cur->parent->parent->rch == cur->parent && cur->parent->rch == cur) { // RR
170 left_rotate(cur->parent, 1);
172 throw std::invalid_argument("Undefined behaviour");
176 /****************************************
178 ****************************************/
179 void insert(T elem) {
180 node * new_node = new node(elem, RED);
181 if (root == nullptr) {
187 /****************************************
188 * find a place to insert binary *
189 ****************************************/
191 if (new_node->val == curr->val) {
195 if (new_node->val < curr->val) { // идем либо влево, либо вправо
196 if (curr->lch == nullptr) {
197 curr->lch = new_node;
198 new_node->parent = curr;
204 if (curr->rch == nullptr) {
205 curr->rch = new_node;
206 new_node->parent = curr;
213 /****************************************
214 * then trying to repair tree invariant *
215 ****************************************/
216 // check if all is okey - parent is black
217 node * cur = new_node;
221 size_t cnt_h(node * cur) {
224 return std::max(cnt_h(cur->lch), cnt_h(cur->rch)) + 1;
226 /********************************
228 ********************************/
229 void print(node * cur, bool ind = 0) {
233 std::cout << "\n---OUTPUT---\n";
234 std::cout << "col = " << (cur->cl == BLACK ? "black" : "red") <<
235 ", val = " << cur->val << "| [" << (cur->lch == nullptr ? -1 : cur->lch->val) <<
236 "," << (cur->rch == nullptr ? -1 : cur->rch->val) <<
237 "] parent = " << (cur->parent == nullptr ? -1 : cur->parent->val) << '\n';
242 if (root != nullptr) {
247 return root == nullptr;
249 node * find(node * cur, T& val) {
250 // if not found - return nullptr
251 // else return pointer on node with val
254 if (cur->val == val) {
256 } else if (cur->val < val) {
257 return find(cur->rch, val);
259 return find(cur->lch, val);
266 // find last element for end iterator
267 while (r->rch != nullptr)
271 iterator find(T& val) {
272 node * elem = find(root, val);
273 return elem == nullptr ? end() : iterator(elem, last());
275 node * child_to_delete(node * cur, bool is_left=0) {
276 // move 1 right and while can left
278 if (cur->rch != nullptr)
279 return child_to_delete(cur->rch, 1);
283 if (cur->lch == nullptr)
286 return child_to_delete(cur->lch, 1);
290 // if element exist remove it
291 node * elem = find(root, val);
294 node * me = child_to_delete(elem); // this node will be deleted implicitly
295 // copy value from the node which is about to be deleted...
296 // ...to the node which keep the val to be deleted
300 color get_color(node * n) {
305 void set_color(node * n, color c) {
311 bool is_left_child(node * sib) {
312 if (sib->parent == nullptr)
314 return sib->parent->lch == sib;
316 /*******************************
317 * main is DELETE-function *
318 *******************************/
319 void delete_node(node * me) {
320 node * to_delete = me;
322 // * - means terminal state
323 if (me->parent == nullptr) {
324 if (me->lch != nullptr) {
326 root->parent = nullptr;
327 delete me; // we can have only one left right right child
328 } else if (me->rch != nullptr) {
330 root->parent = nullptr;
339 // make me null double-black node
340 if (is_left_child(me))
341 me->parent->lch = nullptr;
343 me->parent->rch = nullptr;
347 // if me has red child
348 if (get_color(me->lch) == RED || get_color(me->rch) == RED) {
349 node * cop = nullptr;
350 if (get_color(me->lch) == RED) {
355 if (me->parent->rch == me) { // can delete me immediately
356 me->parent->rch = cop;
358 me->parent->lch = cop;
360 cop->parent = me->parent;
361 // make me null double-black node
362 if (is_left_child(to_delete))
363 to_delete->parent->lch = nullptr;
365 to_delete->parent->rch = nullptr;
369 // if both children are black (it mean that they are null moreover)
370 // if we push the problem - we must solve it another time;
373 if (me->parent == nullptr) {
374 if (is_left_child(to_delete))
375 to_delete->parent->lch = nullptr;
377 to_delete->parent->rch = nullptr;
383 // if our sibling is red, but parent is BLACK! - fix it and make some rotation
384 node * sib = sibling(me);
385 if (is_sibling_red(me) && get_color(me->parent) == BLACK && get_color(sib->lch) == BLACK && get_color(sib->rch) == BLACK) {
386 if (is_left_child(me)) {
389 throw std::invalid_argument("Undefined behaviour");
394 // if node's sibling is black and both sibling's children are black
395 // push double-black node up
397 if (get_color(me->parent) == BLACK && get_color(sib) == BLACK && get_color(sib->lch) == BLACK && get_color(sib->rch) == BLACK) {
398 // then we make pushing: sibling gonna be red, parent gonna be double red, me gonna be black
399 set_color(me, BLACK);
401 set_color(me->parent, BLACK);
406 // case 3 - final state when our sibling and it's children are black but me's parent is red
407 if (!is_sibling_red(me) && get_color(me->parent) == RED && get_color(sib->lch) == BLACK && get_color(sib->rch) == BLACK) {
410 set_color(me, BLACK);
411 set_color(me->parent, BLACK);
412 if (is_left_child(to_delete))
413 to_delete->parent->lch = nullptr;
415 to_delete->parent->rch = nullptr;
421 // if me is lch, and me's black sibling has left-red and right-black child
422 // we make right rotation from left-red child
423 // simmetric case if we are right child
425 if (get_color(sib) == BLACK) {
426 if (is_left_child(me) && get_color(sib->lch) == RED && get_color(sib->rch) == BLACK){ // usual case
427 right_rotate(sib->lch, 1);
428 } else if (!is_left_child(me) && get_color(sib->rch) == RED && get_color(sib->lch) == BLACK){ // simmetric
429 left_rotate(sib->rch, 1);
434 // if me is left child, me's sibling is black, sibling's right child is red;
435 // simmetric if me is right child
437 if (get_color(sib) == BLACK) {
438 if (is_left_child(me) && get_color(sib->rch) == RED){ // usual case
440 set_color(sib, me->parent->cl);
441 set_color(me->parent, BLACK);
442 set_color(sib->rch, BLACK);
443 } else if (!is_left_child(me) && get_color(sib->lch) == RED){ // simmetric
444 right_rotate(sib, 0);
445 set_color(sib, me->parent->cl);
446 set_color(me->parent, BLACK);
447 set_color(sib->lch, BLACK);
449 // make me null double-black node
450 if (is_left_child(to_delete))
451 to_delete->parent->lch = nullptr;
453 to_delete->parent->rch = nullptr;
464 // is_end using for end iterator
467 iterator(node * ptr, node * last) : ptr(ptr), last(last) {}
468 node * next(node * p, node * prev = nullptr) {
473 if (p->rch != nullptr && p->rch != prev) {
477 if (p->parent != nullptr) {
478 return next(p->parent, p);
482 node * prev(node * p, node * prev = nullptr) {
487 if (p->lch != nullptr && p->lch != prev) {
491 if (p->parent != nullptr) {
492 return next(p->parent, p);
496 iterator& operator ++ (int) {
500 iterator operator ++ () {
505 iterator& operator -- (int) {
509 iterator operator -- () {
514 node* operator -> () {
517 node* operator -> () const {
523 T& operator * () const {
526 bool operator == (const iterator& other) const {
527 return ptr == other.ptr;
529 bool operator != (const iterator& other) const {
530 return ptr != other.ptr;
533 return ptr == nullptr;
537 iterator it(root, last());
538 // find mostly left node - it'll be begin
539 while(it->lch != nullptr)
544 iterator it(nullptr, last());
546 while(!it.null() && it->lch != nullptr)
556 int i = 0, n = 2000000;
559 //std::cout << a << ' ';
562 while (!st.empty()) {
564 st.erase(*st.begin());
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list