Inkscape
Vector Graphics Editor
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages Concepts
redblacktree.cpp
Go to the documentation of this file.
2//#include <algorithm>
3
4
5#define _REDBLACK_PRINT(x) std::cout << x << std::endl;
6//comment the following if you want output during RedBlack Tree operations
7//#define _REDBLACK_PRINT(x) ;
8
9
10namespace Geom{
11
12
13
14RedBlack* RedBlackTree::search(Rect const &r, int dimension){
15 return search( Interval( r[dimension].min(), r[dimension].max() ) );
16 // TODO get rid of dimension
17 // TODO put 2 trees (X, Y axis in one lump)
18}
19
20/*
21INTERVAL-SEARCH(T, i)
221 x <- root[T]
232 while x != nil[T] and i does not overlap int[x]
243 do if left[x] != nil[T] and max[left[x]] >= low[i]
254 then x <- left[x]
265 else x <- right[x]
276 return x
28
29Two intervals i,x overlap in the 4 following cases:
30 1) |--------| i
31 |---| x
32
33 2) |-----| i
34 |----------| x
35
36 3) |------| i
37 |------| x
38
39 4) |----| i
40 |----| x
41
42And do not overlap when (the one os left or right of the other)
43 1) |--------| i
44 |---| x
45
46 2) |-----| i
47 |----------| x
48
49
50*/
52 _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: search(Interval i) : (" << i.min() << ", " << i.max() << ")" )
53 RedBlack *x;
54 x = root;
55
56 while( x!=0 &&
57 ( i.max() < x->interval.min() ||
58 i.min() > x->interval.max() )
59 ){
60 _REDBLACK_PRINT( "(" << x->data << ": " << x->key() << ", " << x->high() << " : " << x->subtree_max << ") "
61 << " i do not overlap with x")
62
63 if(x->left != 0 && (x->left)->subtree_max >= i.min() ){
64 x = x->left;
65 }
66 else{
67 x = x->right;
68 }
69 }
70 _REDBLACK_PRINT( "RETURN: search" << std::endl )
71 return x;
72}
73
74
75
76void RedBlackTree::insert(Rect const &r, int shape, int dimension) {
77 _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: insert(Rect, int, dimension): " << " dimension:" << dimension << " shape:" << shape )
78 insert(r[dimension].min(), r[dimension].max(), shape);
79 _REDBLACK_PRINT( "RETURN: insert(Rect, int, dimension)")
80}
81
82// source: book pp 251
83void RedBlackTree::insert(Coord dimension_min, Coord dimension_max, int shape) {
84 _REDBLACK_PRINT( std::endl << "ENTER: insert(Coord, Coord, int): " << dimension_min << ", " << dimension_max << " , shape: " << shape )
85 // x is the new node we insert
86 RedBlack *x = new RedBlack();
87 x->interval = Interval( dimension_min, dimension_max );
88 x->data = shape;
89 x->isRed = true;
90
91 _REDBLACK_PRINT( " x: " << x << " KEY: " << x->key() << " high: " << x->high() )
92
93 tree_insert(x);
94
95 print_tree();
96
97 _REDBLACK_PRINT( " Begin coloring" )
98 // we now do the coloring of the tree.
99 _REDBLACK_PRINT( " while( x!= root && (x->parent)->isRed )" )
100 while( x!= root && (x->parent)->isRed ){
101 _REDBLACK_PRINT( " ((x->parent)->parent)->left:" << ((x->parent)->parent)->left << " ((x->parent)->parent)->right:" << ((x->parent)->parent)->right )
102
103 if( x->parent == ((x->parent)->parent)->left ){
104 _REDBLACK_PRINT( " Left:" )
105 RedBlack *y = new RedBlack;
106 y = ((x->parent)->parent)->right;
107 if( y == 0 ){
108 /*
109 This 1st brach is not in the book, but is needed. We must check y->isRed but it is
110 undefined, so we get segfault. But 0 (undefined) means that y is a leaf, so it is
111 black by definition. So, do the same as in the else part.
112 */
113 _REDBLACK_PRINT( " y==0" )
114 if( x == (x->parent)->right ){
115 x = x->parent;
116 left_rotate(x);
117 }
118 (x->parent)->isRed = false;
119 ((x->parent)->parent)->isRed = true;
120 right_rotate((x->parent)->parent);
121 }
122 else if( y->isRed ){
123 _REDBLACK_PRINT( " y->isRed" )
124 (x->parent)->isRed = false;
125 y->isRed = false;
126 ((x->parent)->parent)->isRed = true;
127 x = (x->parent)->parent;
128 }
129 else{
130 _REDBLACK_PRINT( " !( y->isRed)" )
131 if( x == (x->parent)->right ){
132 x = x->parent;
133 left_rotate(x);
134 }
135 (x->parent)->isRed = false;
136 ((x->parent)->parent)->isRed = true;
137 right_rotate((x->parent)->parent);
138 }
139 }
140 else{ // this branch is the same with the above if clause with "right", "left" exchanged
141 _REDBLACK_PRINT( " Right:" )
142 RedBlack *y = new RedBlack;
143 y = ((x->parent)->parent)->left;
144 if( y == 0 ){
145 /*
146 This 1st brach is not in the book, but is needed. We must check y->isRed but it is
147 undefined, so we get segfault. But 0 (undefined) means that y is a leaf, so it is
148 black by definition. So, do the same as in the else part.
149 */
150 _REDBLACK_PRINT( " y==0" )
151 if( x == (x->parent)->left ){
152 x = x->parent;
153 right_rotate(x);
154 }
155 (x->parent)->isRed = false;
156 ((x->parent)->parent)->isRed = true;
157 left_rotate((x->parent)->parent);
158 }
159 else if( y->isRed ){
160 _REDBLACK_PRINT( " y->isRed" )
161 (x->parent)->isRed = false;
162 y->isRed = false;
163 ((x->parent)->parent)->isRed = true;
164 x = (x->parent)->parent;
165 }
166 else{
167 _REDBLACK_PRINT( " !( y->isRed)" )
168 if( x == (x->parent)->left ){
169 x = x->parent;
170 right_rotate(x);
171 }
172 (x->parent)->isRed = false;
173 ((x->parent)->parent)->isRed = true;
174 left_rotate((x->parent)->parent);
175 }
176 }
177 }
178 root->isRed = false;
179
180 // update the max value with a slow/stupid yet certain way, walking all the tree :P
181 // TODO find better way
182 _REDBLACK_PRINT( " Update max" )
183
185
186 _REDBLACK_PRINT( "RETURN: insert(Coord, Coord, int)" << std::endl)
187}
188
189// from book p. 266)
191 // x->right != 0 (assumption book page 266)
192 // ??? hm problem ???
193 _REDBLACK_PRINT( "ENTER: left_rotate" )
194 RedBlack* y = new RedBlack;
195 y = x->right;
196 x->right = y->left;
197
198 if( y->left != 0){
199 (y->left)->parent = x;
200 }
201
202 y->parent = x->parent;
203
204 if( x->parent == 0){
205 root = y;
206 }
207 else{
208 if( x == (x->parent)->left ){
209 (x->parent)->left = y;
210 }
211 else{
212 (x->parent)->right = y;
213 }
214 }
215 y->left = x;
216 x->parent = y;
217 _REDBLACK_PRINT( "RETURN: left_rotate" << std::endl )
218}
219
220// from book p. 266: right_rotate is inverse of left_rotate
221// same to left_rotate with "right", "left" exchanged
223 // x->right != 0 (assumption book page 266)
224 // ??? hm problem ??
225 _REDBLACK_PRINT( "ENTER: right_rotate" )
226 RedBlack* y = new RedBlack;
227
228 _REDBLACK_PRINT( "x->left: " << x->left )
229 y = x->left;
230 x->left = y->right;
231
232 if( y->right != 0){
233 (y->right)->parent = x;
234 }
235
236 y->parent = x->parent;
237
238 if( x->parent == 0){
239 root = y;
240 }
241 else{
242 if( x == (x->parent)->left ){
243 (x->parent)->left = y;
244 }
245 else{
246 (x->parent)->right = y;
247 }
248 }
249 y->right = x;
250 x->parent = y;
251 _REDBLACK_PRINT( "RETURN: right_rotate" << std::endl )
252}
253
254// insertion in binary search tree: book page 251
255// then the redblack insert performs the coloring
257 _REDBLACK_PRINT( "ENTER: tree_insert(RedBlack* z)" )
258 RedBlack* y = 0; // y <- nil
259
260 RedBlack* x = root;
261
262 _REDBLACK_PRINT( " while x!=0 " )
263 while( x != 0 ){
264 y = x;
265// _REDBLACK_PRINT( " x:" << x << " y:" << y << " z:" << z )
266 _REDBLACK_PRINT( " z->key: " << z->key() << " y->key: " << y->key() << " compare")
267 if( z->key() < x->key() ){
268 _REDBLACK_PRINT( " z smaller: go left" )
269 x = x->left;
270 }
271 else{
272 _REDBLACK_PRINT( " z bigger: go right" )
273 x = x->right;
274 }
275 }
276
277 _REDBLACK_PRINT( " z->parent = y" )
278 z->parent = y;
279
280 if( y == 0 ){
281 _REDBLACK_PRINT( " set z root (empty tree)" )
282 root = z;
283 }
284 else{
285 _REDBLACK_PRINT( " z->key: " << z->key() << " y->key: " << y->key() << " compare")
286 if( z->key() < y->key() ){
287 _REDBLACK_PRINT( " z->key() smaller: y->left = z; " )
288 y->left = z;
289 }
290 else{
291 _REDBLACK_PRINT( " z->key() bigger: y->right = z " )
292 y->right = z;
293 }
294 }
295 _REDBLACK_PRINT( "RETURN: tree_insert(RedBlack* z)" << std::endl )
296}
297
298
299/*
300RB-DELETE(T, z)
301 1 if left[z] = nil[T] or right[z] = nil[T]
302 2 then y <- z
303 3 else y <- TREE-SUCCESSOR(z)
304 4 if left[y] != nil[T]
305 5 then x <- left[y]
306 6 else x <- right[y]
307 7 p[x] <- p[y]
308 8 if p[y] = nil[T]
309 9 then root[T] <- x
31010 else if y = left[p[y]]
31111 then left[p[y]] <- x
31212 else right[p[y]] <- x
31313 if y != z
31414 then key[z] <- key[y]
31515 copy y's satellite data into z
31616 if color[y] = BLACK
31717 then RB-DELETE-FIXUP(T, x)
31818 return y
319*/
321 _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: earse(z)" )
322 RedBlack* x = new RedBlack();
323 RedBlack* y = new RedBlack();
324 if( z->left == 0 || z->right == 0 ){
325 y = z;
326 }
327 else{
328 y = tree_successor(z);
329 }
330
331 if( y->left != 0 ){
332 x = y->left;
333 }
334 else{
335 x = y->right;
336 }
337
338 x->parent = y->parent;
339
340 if( y->parent == 0){
341 root = x;
342 }
343 else {
344 if( y == (y->parent)->left ){
345 (y->parent)->left = x;
346 }
347 else{
348 (y->parent)->right = x;
349 }
350 }
351
352 if( y != z){
353 z->interval = y->interval ; // key[z] <- key[y] TODO check this
354 //copy y's satellite data into z
355 z->data = y->data;
356 z->isRed = y->isRed;
357
358 z->left = y->left;
359 z->right = y->right;
360 z->parent = y->parent;
361 }
362
363 if( y->isRed == false){
364 erase_fixup(x);
365 }
366
367 _REDBLACK_PRINT( "Update max" )
369
370 _REDBLACK_PRINT( "RETURN: erase" )
371 return y;
372}
373
374/*
375RB-DELETE-FIXUP(T, x)
376 1 while x != root[T] and color[x] = BLACK
377 2 do if x = left[p[x]]
378 3 then w <- right[p[x]]
379 4 if color[w] = RED
380 5 then color[w] <- BLACK Case 1
381 6 color[p[x]] <- RED Case 1
382 7 LEFT-ROTATE(T, p[x]) Case 1
383 8 w <- right[p[x]]
384 9 if color[left[w]] = BLACK and color[right[w]] = BLACK
38510 then color[w] <- RED Case 2
38611 x p[x] Case 2
38712 else if color[right[w]] = BLACK
38813 then color[left[w]] <- BLACK Case 3
38914 color[w] <- RED Case 3
39015 RIGHT-ROTATE(T, w) Case 3
39116 w <- right[p[x]] Case 3
39217 color[w] <- color[p[x]] Case 4
39318 color[p[x]] <- BLACK Case 4
39419 color[right[w]] <- BLACK Case 4
39520 LEFT-ROTATE(T, p[x]) Case 4
39621 x <- root[T] Case 4
39722 else (same as then clause with "right" and "left" exchanged)
39823 color[x] <- BLACK
399*/
401 RedBlack* w = 0;
402 while( x != root && x->isRed == false ){
403 if( x == (x->parent)->left ){
404 w = (x->parent)->right;
405 if(w->isRed == true){
406 w->isRed = false;
407 (w->parent)->isRed = true;
409 w = (x->parent)->right;
410 }
411 if( (w->left)->isRed == false && (w->right)->isRed == false ){
412 w->isRed = true;
413 x = x->parent; // TODO understand why this happens ???
414 }
415 else{
416 if( (w->right)->isRed == false ){
417 (w->left)->isRed = false;
419 w = (x->parent)->right;
420 }
421 else{ // TODO ??? is this correct ???
422 w->isRed = (x->parent)->isRed;
423 (x->parent)->isRed = false;
424 (w->right)->isRed = false;
426 x = root; // TODO ??? is this correct ???
427 }
428 }
429 }
430 else{ // same as then clause with "right" and "left" exchanged
431 w = (x->parent)->left;
432 if(w->isRed == true){
433 w->isRed = false;
434 (w->parent)->isRed = true;
436 w = (x->parent)->left;
437 }
438 if( (w->right)->isRed == false && (w->left)->isRed == false ){
439 w->isRed = true;
440 x = x->parent; // ??? is this correct ???
441 }
442 else{
443 if( (w->left)->isRed == false ){
444 (w->right)->isRed = false;
445 left_rotate(w);
446 w = (x->parent)->left;
447 }
448 else{ // TODO ??? is this correct ???
449 w->isRed = (x->parent)->isRed;
450 (x->parent)->isRed = false;
451 (w->left)->isRed = false;
453 x = root; // TODO ??? is this correct ???
454 }
455 }
456 }
457 }
458 x->isRed = false;
459}
460
461
463 std::cout << "Print RedBlackTree status:" << std::endl;
465}
466
467
469 int oops =0;
470 if( x != 0 ){
472 std::cout<< "(" << x->data << ": " << x->key() << ", " << x->high() << " : " << x->subtree_max << ") " ;
473
474 if( x->left != 0 ){
475 std::cout<< "L:(" << (x->left)->data << ", " << (x->left)->key() << ") " ;
476 if( x->key() < (x->left)->key()){
477 std::cout<<" !!! ";
478 oops = 1;
479 }
480 }
481 else{
482 std::cout<< "L:0 " ;
483 }
484
485 if( x->right != 0 ){
486 std::cout<< "R:(" << (x->right)->data << ", "<< (x->right)->key() << ") " ;
487 if( x->key() > (x->right)->key() ){
488 std::cout<<" !!! ";
489 oops = 1;
490 }
491 }
492 else{
493 std::cout<< "R:0 " ;
494 }
495
496 if(oops){
497 std::cout<<" ....... !!! Problem " << oops ;
498 }
499 std::cout << std::endl;
501 }
502}
503
504// not an norder walk of the tree
506 Coord max_left, max_right;
507 if( x != 0 ){
508 update_max(x->left);
509 update_max(x->right);
510
511 // check for child
512 // if child is Nil then max = DBL_MIN
513 // could there be problems when comparing for max between two DBL_MIN ???
514 if( x->left == 0 ){
515 max_left = DBL_MIN ;
516 }
517 else{
518 max_left = (x->left)->subtree_max;
519 }
520
521 if( x->right == 0 ){
522 max_right = DBL_MIN ;
523 }
524 else{
525 max_right = (x->right)->subtree_max;
526 }
527
528 //find max of: x->high(), max_left, max_right
529 Coord temp_max;
530 temp_max = std::max( x->high(), max_left );
531 temp_max = std::max( temp_max, max_right );
532 x->subtree_max = temp_max;
533
534 }
535}
536
537
539 _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: tree_minimum" )
540 while( x->left <- 0 ) {
541 x->left = x;
542 }
543 _REDBLACK_PRINT( "RETURN: tree_minimum" << std::endl )
544 return x;
545}
546
548 _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: tree_successor" )
549 if( x->right <- 0 ){
550 _REDBLACK_PRINT( "RETURN: tree_successor" << std::endl )
551 return tree_minimum(x);
552 }
553 RedBlack* y = x->parent;
554 _REDBLACK_PRINT( "y->parent: y->parent" )
555 while( y <- 0 && x == y->right ){
556 x = y;
557 y = y->parent;
558 }
559 _REDBLACK_PRINT( "RETURN: tree_successor" << std::endl )
560 return y;
561}
562
563
564};
565
566/*
567 Local Variables:
568 mode:c++
569 c-file-style:"stroustrup"
570 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
571 indent-tabs-mode:nil
572 fill-column:99
573 End:
574*/
575// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
constexpr C min() const
constexpr C max() const
Range of real numbers that is never empty.
Definition interval.h:59
Axis aligned, non-empty rectangle.
Definition rect.h:92
void update_max(RedBlack *x)
void left_rotate(RedBlack *x)
void erase_fixup(RedBlack *x)
RedBlack * tree_successor(RedBlack *x)
RedBlack * tree_minimum(RedBlack *x)
void insert(Rect const &r, int shape, int dimension)
RedBlack * search(Rect const &r, int dimension)
void inorder_tree_walk(RedBlack *x)
void right_rotate(RedBlack *x)
void tree_insert(RedBlack *x)
void erase(Rect const &r)
RedBlack * right
RedBlack * left
Interval interval
RedBlack * parent
const double w
Definition conic-4.cpp:19
static char const *const parent
Definition dir-util.cpp:70
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
Various utility functions.
Definition affine.h:22
MultiDegree< n > max(MultiDegree< n > const &p, MultiDegree< n > const &q)
Returns the maximal degree appearing in the two arguments for each variables.
Definition sbasisN.h:158
Piecewise< SBasis > min(SBasis const &f, SBasis const &g)
Return the more negative of the two functions pointwise.
static cairo_user_data_key_t key
Implementation of Red-Black Tree as described in Intorduction to Algorithms.
static const Point data[]