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 | 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