1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

fix the remaining bugs with tree delete that testing found.

the binary tree should work reasonably well now for delete.
insert always worked fine.

(This used to be ctdb commit 452cda26b206549504480b77483308b44cfa8b01)
This commit is contained in:
Ronnie Sahlberg 2007-07-30 09:09:34 +10:00
parent 8df376b3f0
commit c76f323f73

View File

@ -406,6 +406,14 @@ delete_node(trbt_node_t *node)
{
trbt_node_t *parent, *child, dc;
/* This node has two child nodes, then just copy the content
from the next smaller node with this node and delete the
predecessor instead.
The predecessor is guaranteed to have at most one child
node since its right arm must be NULL
(It must be NULL since we are its sucessor and we are above
it in the tree)
*/
if (node->left != NULL && node->right != NULL) {
/* This node has two children, just copy the data */
/* find the predecessor */
@ -430,14 +438,20 @@ delete_node(trbt_node_t *node)
}
/* There is at most one child to this node to be deleted */
child = node->left;
if (node->right) {
child = node->right;
}
/* we didnt have a proper child so create a dummy child */
/* If the node to be deleted did not have any child at all we
create a temporary dummy node for the child and mark it black.
Once the delete of the node is finished, we remove this dummy
node, which is simple to do since it is guaranteed that it will
still not have any children after the delete operation.
This is because we dont represent the leaf-nodes as actual nodes
in this implementation.
*/
if (!child) {
child = &dc;
child->tree = node->tree;
@ -455,11 +469,12 @@ delete_node(trbt_node_t *node)
} else {
parent->right = child;
}
// } else {
// node->tree->tree = child;
} else {
node->tree->tree = child;
}
child->parent = node->parent;
if (node->rb_color == TRBT_BLACK) {
if (trbt_get_color(child) == TRBT_RED) {
child->rb_color = TRBT_BLACK;
@ -468,8 +483,22 @@ delete_node(trbt_node_t *node)
}
}
/* If we had to create a temporary dummy node to represent a black
leaf child we now has to delete it.
This is simple since this dummy node originally had no children
and we are guaranteed that it will also not have any children
after the node has been deleted and any possible rotations
have occured.
The only special case is if this was the last node of the tree
in which case we have to reset the root to NULL as well.
Othervise it is enough to just unlink the child from its new
parent.
*/
if (child == &dc) {
if (child == child->parent->left) {
if (child->parent == NULL) {
node->tree->tree = NULL;
} else if (child == child->parent->left) {
child->parent->left = NULL;
} else {
child->parent->right = NULL;
@ -647,6 +676,22 @@ test_tree(void)
int cnt=0;
tree=trbt_create(talloc_new(NULL));
#if 0
for(i=0;i<10;i++){
printf("adding node %i\n",i);
trbt_insert32(tree, i, NULL);
print_tree(tree);
}
printf("deleting node %i\n",3);
trbt_delete32(tree, 3);
print_tree(tree);
for(i=0;i<10;i++){
printf("deleting node %i\n",i);
trbt_delete32(tree, i);
print_tree(tree);
}
exit(0);
#endif
while(++cnt){
int i;
printf("iteration : %d\n",cnt);