summaryrefslogtreecommitdiffstats
path: root/zix
diff options
context:
space:
mode:
Diffstat (limited to 'zix')
-rw-r--r--zix/btree.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/zix/btree.c b/zix/btree.c
index 69e7575..03f0aa9 100644
--- a/zix/btree.c
+++ b/zix/btree.c
@@ -526,21 +526,26 @@ zix_btree_remove(ZixBTree* const t,
}
} else if (equal) {
// Found in internal node
- if (!zix_btree_node_is_minimal(n->children[i])) {
+ const size_t l_size = n->children[i]->n_vals;
+ const size_t r_size = n->children[i + 1]->n_vals;
+ if (zix_btree_node_is_minimal(n->children[i]) &&
+ zix_btree_node_is_minimal(n->children[i + 1])) {
+ // Both preceding and succeeding child are minimal
+ n = zix_btree_merge(t, n, i);
+ } else if (l_size >= r_size) {
// Left child can remove without merge
+ assert(!zix_btree_node_is_minimal(n->children[i]));
*out = n->vals[i];
n->vals[i] = zix_btree_remove_max(t, n->children[i]);
--t->size;
return ZIX_STATUS_SUCCESS;
- } else if (!zix_btree_node_is_minimal(n->children[i + 1])) {
+ } else {
// Right child can remove without merge
+ assert(!zix_btree_node_is_minimal(n->children[i + 1]));
*out = n->vals[i];
n->vals[i] = zix_btree_remove_min(t, n->children[i + 1]);
--t->size;
return ZIX_STATUS_SUCCESS;
- } else {
- // Both preceding and succeeding child are minimal
- n = zix_btree_merge(t, n, i);
}
} else {
// Not found in internal node, key is in/under children[i]