Commit ef6ccfbcbe379737fc4b3d52388f28f8d6192806
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,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 | void | 94 | void |
95 | rotateLeft(struct element ** tree, struct element * node) | 95 | rotateLeft(struct element ** tree, struct element * node) |
@@ -139,6 +139,23 @@ rotateRight(struct element ** tree, struct element * node) | @@ -139,6 +139,23 @@ rotateRight(struct element ** tree, struct element * node) | ||
139 | node->parent = leftChild; | 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 | * insert element in tree | 160 | * insert element in tree |
144 | */ | 161 | */ |
@@ -269,7 +286,10 @@ struct element * deleteOneChild(struct element **, struct element *); | @@ -269,7 +286,10 @@ struct element * deleteOneChild(struct element **, struct element *); | ||
269 | struct element * | 286 | struct element * |
270 | deleteElement(struct element ** tree, int data) | 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 | // find the relevant node and it's parent | 294 | // find the relevant node and it's parent |
275 | while (NULL != node && node->data != data) { | 295 | while (NULL != node && node->data != data) { |
@@ -285,27 +305,150 @@ deleteElement(struct element ** tree, int data) | @@ -285,27 +305,150 @@ deleteElement(struct element ** tree, int data) | ||
285 | return node; | 305 | return node; |
286 | } | 306 | } |
287 | 307 | ||
308 | + del_node = node; | ||
309 | + | ||
288 | // now our cases follows...the first one is the same as with | 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 | // case 1: two children | 313 | // case 1: two children |
292 | if (NULL != node->left && NULL != node->right) { | 314 | if (NULL != node->left && NULL != node->right) { |
293 | struct element * successor = findInOrderSuccessor(node); | 315 | struct element * successor = findInOrderSuccessor(node); |
294 | 316 | ||
295 | node->data = successor->data; | 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 | void | 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 | struct element * previous = tree; | 449 | struct element * previous = tree; |
307 | struct element * node = tree; | 450 | struct element * node = tree; |
308 | - int depth = 1; | 451 | + int depth = 1; |
309 | 452 | ||
310 | /* | 453 | /* |
311 | * I think this has something like O(n+log(n)) on a ballanced | 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,7 +472,7 @@ traverse(struct element * tree, void (*cb)(int, int)) | ||
329 | * If there are no more elements to the left or we | 472 | * If there are no more elements to the left or we |
330 | * came from the left, process data. | 473 | * came from the left, process data. |
331 | */ | 474 | */ |
332 | - cb(node->data, depth); | 475 | + cb(node->data, depth, node->color); |
333 | previous = node; | 476 | previous = node; |
334 | 477 | ||
335 | if (NULL != node->right) { | 478 | if (NULL != node->right) { |
@@ -350,184 +493,16 @@ traverse(struct element * tree, void (*cb)(int, int)) | @@ -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 | int i; | 498 | int i; |
356 | 499 | ||
357 | - printf("%02d(%02d)", data, depth); | 500 | + printf("%s %02d(%02d)", (color==rbRed)?"R":"B", data, depth); |
358 | for (i=0; i<depth; i++) printf("-"); | 501 | for (i=0; i<depth; i++) printf("-"); |
359 | puts(""); | 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,7 +523,6 @@ main(int argc, char * argv[]) | ||
548 | puts("traverse"); | 523 | puts("traverse"); |
549 | traverse(root, printElement); | 524 | traverse(root, printElement); |
550 | 525 | ||
551 | - /* | ||
552 | free(deleteElement(&root, 8)); | 526 | free(deleteElement(&root, 8)); |
553 | puts("traverse"); | 527 | puts("traverse"); |
554 | traverse(root, printElement); | 528 | traverse(root, printElement); |
@@ -580,7 +554,6 @@ main(int argc, char * argv[]) | @@ -580,7 +554,6 @@ main(int argc, char * argv[]) | ||
580 | free(deleteElement(&root, 12)); | 554 | free(deleteElement(&root, 12)); |
581 | puts("traverse"); | 555 | puts("traverse"); |
582 | traverse(root, printElement); | 556 | traverse(root, printElement); |
583 | - */ | ||
584 | 557 | ||
585 | return 0; | 558 | return 0; |
586 | } | 559 | } |
Please
register
or
login
to post a comment