I have found some code online for red black trees, and am trying to implement it.
I do not want to use the assert
function though which the original code has located here
I am getting a seg fault on the line n->color = child->color;
just before the delete fix. After debugging I discovered that the child did not exist in this case, and so the reason for the assert statement in the original code. I decided to add what I thought was appropriate with the additional if clause around everything from where child is dealt with downward.
However, now the program does not actually delete, because if the child does not exist, it never makes it into the loop. After trial and error I still cannot find where to close the if clause in order to take the place of the assert statement properly.
Please let me know your ideas!
Here is my "translated" code without the assert, and using an if statement instead.
void delete_node(int key)
{
node* child;
node* n ;
n = searchTree(key);
if(n == NULL)return;
if(n->left != NULL && n->right != NULL)
{
node* pred = n->left;
while(pred->right != NULL)
pred = pred->right;
n->value = pred->value;
n = pred;
}
if(n->right != NULL || n->left != NULL){
child = n->right == NULL ? n->left : n->right;
if(n->color == 'b')
{
n->color = child->color;
delete_fix1(n);
}
swap_nodes(n, child);
if(n->parent == NULL && child != NULL)
child->color = 'b';
free(n);
}
}
Test data (Seg Fault occurs when attempting to delete 4): i stand for insert (insert occurs flawlessly as far as I can tell) d stands for delete
i 7
i 8
i 1
d 8
i 4
i 10
d 4
i 11
This:
assert(n->left == NULL || n->right == NULL)
Is nowhere near this:
if (n->right != NULL || n->left != NULL)
Recheck your translation. The assert states that one of them must be NULL. your if-expr evals true if either are not NULL. Your if-expr passes if both are non-null, where the assert would fail. Likewise, your if-expr fails if both are NULL, while the assert would pass.
Don't take shortcuts when doing this kinda of thing. First. keep the asserts regardless of your added checks. Second, until it is up and working, copy the assert clauses verbatim in your if (expr): or (!(expr)) for bailout conditions.
verbatim check:
assert(n->left == NULL || n->right == NULL)
if (n->left == NULL || n->right == NULL)...
bailout check:
assert(n->left == NULL || n->right == NULL)
if (!(n->left == NULL || n->right == NULL))
bailout loud.
EDIT Translation of linked code with integrated if-expr
void rbtree_delete(rbtree t, void* key, compare_func compare)
{
node child;
node n = lookup_node(t, key, compare);
if (n == NULL) return; /* Key not found, do nothing */
if (n->left != NULL && n->right != NULL) {
/* Copy key/value from predecessor and then delete it instead */
node pred = maximum_node(n->left);
n->key = pred->key;
n->value = pred->value;
n = pred;
}
assert(n->left == NULL || n->right == NULL);
if (n->left == NULL || n->right == NULL) // << note: SAME as above
{
child = n->right == NULL ? n->left : n->right;
if (node_color(n) == BLACK) {
n->color = node_color(child);
delete_case1(t, n);
}
replace_node(t, n, child);
if (n->parent == NULL && child != NULL)
child->color = BLACK;
free(n);
}
verify_properties(t);
}