version 1.1, 2008/11/14 11:58:08 |
version 1.2, 2008/11/22 16:33:42 |
|
|
* Adapted from the following code written by Emin Martinian: |
* Adapted from the following code written by Emin Martinian: |
* http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html |
* http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html |
* |
* |
|
* Copyright (c) 2001 Emin Martinian |
|
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that neither the name of Emin |
* modification, are permitted provided that neither the name of Emin |
* Martinian nor the names of any contributors are be used to endorse or |
* Martinian nor the names of any contributors are be used to endorse or |
|
|
#include "redblack.h" |
#include "redblack.h" |
|
|
#ifndef lint |
#ifndef lint |
__unused static const char rcsid[] = "$Sudo: redblack.c,v 1.8 2008/11/09 14:13:12 millert Exp $"; |
__unused static const char rcsid[] = "$Sudo: redblack.c,v 1.10 2008/11/22 15:01:25 millert Exp $"; |
#endif /* lint */ |
#endif /* lint */ |
|
|
static void rbrepair __P((struct rbtree *, struct rbnode *)); |
static void rbrepair __P((struct rbtree *, struct rbnode *)); |
|
|
} |
} |
|
|
/* |
/* |
* Delete victim from tree and return its data pointer. |
* Delete node 'z' from the tree and return its data pointer. |
*/ |
*/ |
void * |
void *rbdelete(tree, z) |
rbdelete(tree, victim) |
struct rbtree* tree; |
struct rbtree *tree; |
struct rbnode* z; |
struct rbnode *victim; |
|
{ |
{ |
struct rbnode *pred, *succ; |
struct rbnode *x, *y; |
void *data; |
void *data = z->data; |
|
|
if (victim->left != rbnil(tree) && victim->right != rbnil(tree)) { |
if (z->left == rbnil(tree) || z->right == rbnil(tree)) |
succ = rbsuccessor(tree, victim); |
y = z; |
pred = succ->left == rbnil(tree) ? succ->right : succ->left; |
else |
if (succ->parent == rbroot(tree)) { |
y = rbsuccessor(tree, z); |
pred->parent = rbroot(tree); |
x = (y->left == rbnil(tree)) ? y->right : y->left; |
rbfirst(tree) = pred; |
|
} else { |
|
if (succ == succ->parent->left) |
|
succ->parent->left = pred; |
|
else |
|
succ->parent->right = pred; |
|
} |
|
if ((succ->color == black)) |
|
rbrepair(tree, pred); |
|
|
|
succ->left = victim->left; |
if ((x->parent = y->parent) == rbroot(tree)) { |
succ->right = victim->right; |
rbfirst(tree) = x; |
succ->parent = victim->parent; |
|
succ->color = victim->color; |
|
victim->left->parent = victim->right->parent = succ; |
|
if (victim == victim->parent->left) |
|
victim->parent->left = succ; |
|
else |
|
victim->parent->right = succ; |
|
data = victim->data; |
|
efree(victim); |
|
} else { |
} else { |
pred = victim->left == rbnil(tree) ? victim->right : victim->left; |
if (y == y->parent->left) |
if (victim->parent == rbroot(tree)) { |
y->parent->left = x; |
pred->parent = rbroot(tree); |
else |
rbfirst(tree) = pred; |
y->parent->right = x; |
} else { |
|
if (victim == victim->parent->left) |
|
victim->parent->left = pred; |
|
else |
|
victim->parent->right = pred; |
|
} |
|
if (victim->color == black) |
|
rbrepair(tree, pred); |
|
data = victim->data; |
|
efree(victim); |
|
} |
} |
return(data); |
if (y->color == black) |
|
rbrepair(tree, x); |
|
if (y != z) { |
|
y->left = z->left; |
|
y->right = z->right; |
|
y->parent = z->parent; |
|
y->color = z->color; |
|
z->left->parent = z->right->parent = y; |
|
if (z == z->parent->left) |
|
z->parent->left = y; |
|
else |
|
z->parent->right = y; |
|
} |
|
free(z); |
|
|
|
return (data); |
} |
} |
|
|
/* |
/* |
|
|
{ |
{ |
struct rbnode *sibling; |
struct rbnode *sibling; |
|
|
while (node->color == black && node != rbfirst(tree)) { |
while (node->color == black) { |
if (node == node->parent->left) { |
if (node == node->parent->left) { |
sibling = node->parent->right; |
sibling = node->parent->right; |
if (sibling->color == red) { |
if (sibling->color == red) { |
|
|
node->parent->color = black; |
node->parent->color = black; |
sibling->right->color = black; |
sibling->right->color = black; |
rotate_left(tree, node->parent); |
rotate_left(tree, node->parent); |
return; /* XXX */ |
break; |
} |
} |
} else { /* if (node == node->parent->right) */ |
} else { /* if (node == node->parent->right) */ |
sibling = node->parent->left; |
sibling = node->parent->left; |
|
|
node->parent->color = black; |
node->parent->color = black; |
sibling->left->color = black; |
sibling->left->color = black; |
rotate_right(tree, node->parent); |
rotate_right(tree, node->parent); |
return; /* XXX */ |
break; |
} |
} |
} |
} |
} |
} |
node->color = black; |
|
} |
} |