forked from vieter-v/libvieter
feat(tree): first attempt at wikipedia pseudo code
parent
1d458c68a4
commit
17c2e15385
|
@ -124,6 +124,22 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root,
|
||||||
|
bool dir) {
|
||||||
|
vieter_tree_node *new_root = old_root->children[1 - dir];
|
||||||
|
|
||||||
|
// Right rotation
|
||||||
|
if (dir) {
|
||||||
|
vieter_tree_node_set_child(old_root, new_root->children[1], false);
|
||||||
|
vieter_tree_node_set_child(new_root, old_root, true);
|
||||||
|
} else {
|
||||||
|
vieter_tree_node_set_child(old_root, new_root->children[0], true);
|
||||||
|
vieter_tree_node_set_child(new_root, old_root, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_root;
|
||||||
|
}
|
||||||
|
|
||||||
void vieter_tree_node_remove_balanced(vieter_tree_node *node) {
|
void vieter_tree_node_remove_balanced(vieter_tree_node *node) {
|
||||||
// A red node can only have 0 or 2 children. The node we receive only has
|
// A red node can only have 0 or 2 children. The node we receive only has
|
||||||
// one child at most, so we know if it's red that it doesn't have any
|
// one child at most, so we know if it's red that it doesn't have any
|
||||||
|
@ -145,4 +161,80 @@ void vieter_tree_node_remove_balanced(vieter_tree_node *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The complicated case is when we want to remove a black leaf
|
// The complicated case is when we want to remove a black leaf
|
||||||
|
// https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Removal_of_a_black_non-root_leaf
|
||||||
|
|
||||||
|
vieter_tree_node *parent = node->parent;
|
||||||
|
vieter_tree_node *sibling, *close_nephew, *distant_nephew;
|
||||||
|
bool dir = vieter_tree_node_get(node, vieter_tree_node_right);
|
||||||
|
parent->children[dir] = NULL;
|
||||||
|
|
||||||
|
vieter_tree_node_free(node);
|
||||||
|
|
||||||
|
goto start;
|
||||||
|
|
||||||
|
do {
|
||||||
|
dir = vieter_tree_node_get(node, vieter_tree_node_right);
|
||||||
|
|
||||||
|
start:
|
||||||
|
sibling = parent->children[1 - dir];
|
||||||
|
distant_nephew = sibling->children[1 - dir];
|
||||||
|
close_nephew = sibling->children[dir];
|
||||||
|
|
||||||
|
if (!vieter_tree_node_get(sibling, vieter_tree_node_black))
|
||||||
|
goto case3;
|
||||||
|
|
||||||
|
if (distant_nephew != NULL &&
|
||||||
|
!vieter_tree_node_get(distant_nephew, vieter_tree_node_black))
|
||||||
|
goto case6;
|
||||||
|
|
||||||
|
if (close_nephew != NULL &&
|
||||||
|
!vieter_tree_node_get(close_nephew, vieter_tree_node_black))
|
||||||
|
goto case5;
|
||||||
|
|
||||||
|
if (!vieter_tree_node_get(parent, vieter_tree_node_black))
|
||||||
|
goto case4;
|
||||||
|
|
||||||
|
// Case 2
|
||||||
|
vieter_tree_node_set(sibling, vieter_tree_node_black, false);
|
||||||
|
node = parent;
|
||||||
|
} while ((parent = node->parent) != NULL);
|
||||||
|
|
||||||
|
// Case 1
|
||||||
|
return;
|
||||||
|
|
||||||
|
case3:
|
||||||
|
vieter_tree_node_rotate(parent, dir);
|
||||||
|
vieter_tree_node_set(parent, vieter_tree_node_black, false);
|
||||||
|
vieter_tree_node_set(sibling, vieter_tree_node_black, true);
|
||||||
|
sibling = close_nephew;
|
||||||
|
distant_nephew = sibling->children[1 - dir];
|
||||||
|
|
||||||
|
if (distant_nephew != NULL &&
|
||||||
|
!vieter_tree_node_get(distant_nephew, vieter_tree_node_black))
|
||||||
|
goto case6;
|
||||||
|
|
||||||
|
close_nephew = sibling->children[dir];
|
||||||
|
|
||||||
|
if (close_nephew != NULL &&
|
||||||
|
!vieter_tree_node_get(close_nephew, vieter_tree_node_black))
|
||||||
|
goto case5;
|
||||||
|
|
||||||
|
case4:
|
||||||
|
vieter_tree_node_set(sibling, vieter_tree_node_black, false);
|
||||||
|
vieter_tree_node_set(parent, vieter_tree_node_black, true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case5:
|
||||||
|
vieter_tree_node_rotate(sibling, 1 - dir);
|
||||||
|
vieter_tree_node_set(sibling, vieter_tree_node_black, false);
|
||||||
|
vieter_tree_node_set(close_nephew, vieter_tree_node_black, true);
|
||||||
|
distant_nephew = sibling;
|
||||||
|
sibling = close_nephew;
|
||||||
|
|
||||||
|
case6:
|
||||||
|
vieter_tree_node_rotate(parent, dir);
|
||||||
|
vieter_tree_node_set(sibling, vieter_tree_node_black,
|
||||||
|
vieter_tree_node_get(parent, vieter_tree_node_black));
|
||||||
|
vieter_tree_node_set(parent, vieter_tree_node_black, true);
|
||||||
|
vieter_tree_node_set(distant_nephew, vieter_tree_node_black, true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue