Commit ef6ccfbcbe379737fc4b3d52388f28f8d6192806

Authored by Georg Hopp
1 parent 52755ca9

rbtree insert and delete now as one function and working as expected...still has…

… to be checked on sideeffects.
Showing 1 changed file with 153 additions and 180 deletions
... ... @@ -89,7 +89,7 @@ sibling(struct element * node)
89 89 }
90 90
91 91 /*
92   - * rotations...also needed for rb handling.
  92 + * tree modifications...needed for rb handling.
93 93 */
94 94 void
95 95 rotateLeft(struct element ** tree, struct element * node)
... ... @@ -139,6 +139,23 @@ rotateRight(struct element ** tree, struct element * node)
139 139 node->parent = leftChild;
140 140 }
141 141
  142 +void
  143 +replaceNode(struct element * node1, struct element * node2)
  144 +{
  145 + if (NULL != node1->parent) {
  146 + if (node1 == node1->parent->left) {
  147 + node1->parent->left = node2;
  148 + } else {
  149 + node1->parent->right = node2;
  150 + }
  151 + }
  152 +
  153 + if (NULL != node2) {
  154 + node2->parent = node1->parent;
  155 + }
  156 +}
  157 +
  158 +
142 159 /**
143 160 * insert element in tree
144 161 */
... ... @@ -269,7 +286,10 @@ struct element * deleteOneChild(struct element **, struct element *);
269 286 struct element *
270 287 deleteElement(struct element ** tree, int data)
271 288 {
272   - struct element * node = *tree;
  289 + struct element * node = *tree;
  290 + struct element * del_node;
  291 + struct element * child;
  292 + struct element * s;
273 293
274 294 // find the relevant node and it's parent
275 295 while (NULL != node && node->data != data) {
... ... @@ -285,27 +305,150 @@ deleteElement(struct element ** tree, int data)
285 305 return node;
286 306 }
287 307
  308 + del_node = node;
  309 +
288 310 // now our cases follows...the first one is the same as with
289   - // simple binary search trees.
  311 + // simple binary search trees. Two non null children.
290 312
291 313 // case 1: two children
292 314 if (NULL != node->left && NULL != node->right) {
293 315 struct element * successor = findInOrderSuccessor(node);
294 316
295 317 node->data = successor->data;
296   - node = successor;
  318 + del_node = node = successor;
  319 + }
  320 +
  321 + // delete and rb rebalance...
  322 + while(1) {
  323 + // Precondition: n has at most one non-null child.
  324 + child = (NULL == node->right) ? node->left : node->right;
  325 + replaceNode(node, child);
  326 +
  327 + // delete one child case
  328 + // TODO this is overly complex as simply derived from the function...
  329 + // maybe this can be simplified. Maybe not...check.
  330 + if (node->color == rbBlack) {
  331 + if (NULL != child && child->color == rbRed) {
  332 + child->color = rbBlack;
  333 + // done despite modifying tree itself if neccessary..
  334 + break;
  335 + } else {
  336 + if (NULL == node->parent){
  337 + *tree = 0x0;
  338 + }
  339 + node = child;
  340 + }
  341 + } else {
  342 + if (NULL == node->parent){
  343 + *tree = 0x0;
  344 + }
  345 + break;
  346 + }
  347 +
  348 + // case 1
  349 + if (NULL == node || NULL == node->parent) {
  350 + // done again
  351 + break;
  352 + }
  353 +
  354 + // case 2
  355 + s = sibling(node);
  356 +
  357 + if (NULL != s && s->color == rbRed) {
  358 + node->parent->color = rbRed;
  359 + s->color = rbBlack;
  360 +
  361 + if (node == node->parent->left) {
  362 + rotateLeft(tree, node->parent);
  363 + } else {
  364 + rotateRight(tree, node->parent);
  365 + }
  366 + }
  367 +
  368 + // case 3 / 4
  369 + if (NULL == s || ((s->color == rbBlack) &&
  370 + (s->left->color == rbBlack) &&
  371 + (s->right->color == rbBlack))) {
  372 +
  373 + if (NULL != s) {
  374 + s->color = rbRed;
  375 + }
  376 +
  377 + if (node->parent->color == rbBlack) {
  378 + // case 3
  379 + node = node->parent;
  380 + continue;
  381 + } else {
  382 + // case 4
  383 + node->parent->color = rbBlack;
  384 + // and done again...
  385 + break;
  386 + }
  387 + } else {
  388 + // done...
  389 + break;
  390 + }
  391 +
  392 +
  393 + // case 5
  394 + if (NULL != s && s->color == rbBlack) {
  395 + // this if statement is trivial,
  396 + // due to case 2 (even though case 2 changed the sibling to a
  397 + // sibling's child,
  398 + // the sibling's child can't be red, since no red parent can
  399 + // have a red child).
  400 + //
  401 + // the following statements just force the red to be on the
  402 + // left of the left of the parent,
  403 + // or right of the right, so case 6 will rotate correctly.
  404 + if ((node == node->parent->left) &&
  405 + (s->right->color == rbBlack) &&
  406 + (s->left->color == rbRed)) {
  407 +
  408 + // this last test is trivial too due to cases 2-4.
  409 + s->color = rbRed;
  410 + s->left->color = rbBlack;
  411 +
  412 + rotateRight(tree, s);
  413 + } else if ((node == node->parent->right) &&
  414 + (s->left->color == rbBlack) &&
  415 + (s->right->color == rbRed)) {
  416 + // this last test is trivial too due to cases 2-4.
  417 + s->color = rbRed;
  418 + s->right->color = rbBlack;
  419 +
  420 + rotateLeft(tree, s);
  421 + }
  422 + }
  423 +
  424 + // case 6
  425 + s->color = node->parent->color;
  426 + node->parent->color = rbBlack;
  427 +
  428 + if (node == node->parent->left) {
  429 + s->right->color = rbBlack;
  430 + rotateLeft(tree, node->parent);
  431 + } else {
  432 + s->left->color = rbBlack;
  433 + rotateRight(tree, node->parent);
  434 + }
  435 +
  436 + // done...
  437 + break;
297 438 }
  439 +
  440 + //deleteOneChild(tree, node);
298 441
299   - return deleteOneChild(tree, node);
  442 + return del_node;
300 443 }
301 444
302 445
303 446 void
304   -traverse(struct element * tree, void (*cb)(int, int))
  447 +traverse(struct element * tree, void (*cb)(int, int, enum rbColor))
305 448 {
306 449 struct element * previous = tree;
307 450 struct element * node = tree;
308   - int depth = 1;
  451 + int depth = 1;
309 452
310 453 /*
311 454 * I think this has something like O(n+log(n)) on a ballanced
... ... @@ -329,7 +472,7 @@ traverse(struct element * tree, void (*cb)(int, int))
329 472 * If there are no more elements to the left or we
330 473 * came from the left, process data.
331 474 */
332   - cb(node->data, depth);
  475 + cb(node->data, depth, node->color);
333 476 previous = node;
334 477
335 478 if (NULL != node->right) {
... ... @@ -350,184 +493,16 @@ traverse(struct element * tree, void (*cb)(int, int))
350 493 }
351 494 }
352 495
353   -void printElement(int data, int depth)
  496 +void printElement(int data, int depth, enum rbColor color)
354 497 {
355 498 int i;
356 499
357   - printf("%02d(%02d)", data, depth);
  500 + printf("%s %02d(%02d)", (color==rbRed)?"R":"B", data, depth);
358 501 for (i=0; i<depth; i++) printf("-");
359 502 puts("");
360 503 }
361 504
362 505
363   -void
364   -replaceNode(struct element * node1, struct element * node2)
365   -{
366   - if (NULL != node1->parent) {
367   - if (node1 == node1->parent->left) {
368   - node1->parent->left = node2;
369   - } else {
370   - node1->parent->right = node2;
371   - }
372   - }
373   -
374   - if (NULL != node2) {
375   - node2->parent = node1->parent;
376   - }
377   -}
378   -
379   -void
380   -deleteCase6(struct element ** tree, struct element * node)
381   -{
382   - struct element * s = sibling(node);
383   -
384   - s->color = node->parent->color;
385   - node->parent->color = rbBlack;
386   -
387   - if (node == node->parent->left) {
388   - s->right->color = rbBlack;
389   - rotateLeft(tree, node->parent);
390   - } else {
391   - s->left->color = rbBlack;
392   - rotateRight(tree, node->parent);
393   - }
394   -}
395   -
396   -void
397   -deleteCase5(struct element ** tree, struct element * node)
398   -{
399   - struct element * s = sibling(node);
400   -
401   - if (NULL != s && s->color == rbBlack) {
402   - /*
403   - * this if statement is trivial,
404   - * due to case 2 (even though case 2 changed the sibling to a
405   - * sibling's child,
406   - * the sibling's child can't be red, since no red parent can
407   - * have a red child).
408   - */
409   - /*
410   - * the following statements just force the red to be on the
411   - * left of the left of the parent,
412   - * or right of the right, so case six will rotate correctly.
413   - */
414   - if ((node == node->parent->left) &&
415   - (s->right->color == rbBlack) &&
416   - (s->left->color == rbRed)) {
417   -
418   - /* this last test is trivial too due to cases 2-4. */
419   - s->color = rbRed;
420   - s->left->color = rbBlack;
421   -
422   - rotateRight(tree, s);
423   - } else if ((node == node->parent->right) &&
424   - (s->left->color == rbBlack) &&
425   - (s->right->color == rbRed)) {
426   - /*
427   - * this last test is trivial too due to cases 2-4.
428   - */
429   - s->color = rbRed;
430   - s->right->color = rbBlack;
431   -
432   - rotateLeft(tree, s);
433   - }
434   - }
435   -
436   - deleteCase6(tree, node);
437   -}
438   -
439   -void
440   -deleteCase4(struct element ** tree, struct element * node)
441   -{
442   - struct element * s = sibling(node);
443   -
444   - if ((node->parent->color == rbRed) &&
445   - (NULL == s || ((s->color == rbBlack) &&
446   - (s->left->color == rbBlack) &&
447   - (s->right->color == rbBlack)))) {
448   - if (NULL != s) {
449   - s->color = rbRed;
450   - }
451   - node->parent->color = rbBlack;
452   - } else {
453   - deleteCase5(tree, node);
454   - }
455   -}
456   -
457   -void deleteCase1(struct element **, struct element *);
458   -
459   -void
460   -deleteCase3(struct element ** tree, struct element * node)
461   -{
462   - struct element * s = sibling(node);
463   -
464   - if ((node->parent->color == rbBlack) &&
465   - (NULL == s || ((s->color == rbBlack) &&
466   - (s->left->color == rbBlack) &&
467   - (s->right->color == rbBlack)))) {
468   - if (NULL != s) {
469   - s->color = rbRed;
470   - }
471   - deleteCase1(tree, node->parent);
472   - } else {
473   - deleteCase4(tree, node);
474   - }
475   -}
476   -
477   -void
478   -deleteCase2(struct element ** tree, struct element * node)
479   -{
480   - struct element * s = sibling(node);
481   -
482   - if (NULL != s && s->color == rbRed) {
483   - node->parent->color = rbRed;
484   - s->color = rbBlack;
485   -
486   - if (node == node->parent->left) {
487   - rotateLeft(tree, node->parent);
488   - } else {
489   - rotateRight(tree, node->parent);
490   - }
491   - }
492   -
493   - deleteCase3(tree, node);
494   -}
495   -
496   -void
497   -deleteCase1(struct element ** tree, struct element * node)
498   -{
499   - if (NULL != node && NULL != node->parent) {
500   - deleteCase2(tree, node);
501   - }
502   -}
503   -
504   -struct element *
505   -deleteOneChild(struct element ** tree, struct element * node)
506   -{
507   - /*
508   - * Precondition: n has at most one non-null child.
509   - */
510   - struct element * child = (NULL == node->right) ? node->left : node->right;
511   -
512   - replaceNode(node, child);
513   -
514   - if (node->color == rbBlack) {
515   - if (NULL != child && child->color == rbRed) {
516   - child->color = rbBlack;
517   - } else {
518   - deleteCase1(tree, child);
519   - }
520   - }
521   -
522   - if (NULL == node->parent){
523   - *tree = 0x0;
524   - }
525   -
526   - return node;
527   -}
528   -
529   -
530   -
531 506 /**
532 507 * =======================================================================
533 508 */
... ... @@ -548,7 +523,6 @@ main(int argc, char * argv[])
548 523 puts("traverse");
549 524 traverse(root, printElement);
550 525
551   - /*
552 526 free(deleteElement(&root, 8));
553 527 puts("traverse");
554 528 traverse(root, printElement);
... ... @@ -580,7 +554,6 @@ main(int argc, char * argv[])
580 554 free(deleteElement(&root, 12));
581 555 puts("traverse");
582 556 traverse(root, printElement);
583   - */
584 557
585 558 return 0;
586 559 }
... ...
Please register or login to post a comment