feat(lsm): implement a simple trie remove
This commit is contained in:
parent
682f422e3c
commit
6938c29725
5 changed files with 147 additions and 34 deletions
|
|
@ -18,16 +18,16 @@ lsm_error lsm_bt_node_init(lsm_bt_node **ptr, const char key, void *data) {
|
|||
|
||||
void lsm_bt_node_free(lsm_bt_node *node) { free(node); }
|
||||
|
||||
void lsm_bt_node_free_recursive(lsm_bt_node *node) {
|
||||
void lsm_bt_node_free_tree(lsm_bt_node *node) {
|
||||
if (node->left != NULL) {
|
||||
lsm_bt_node_free_recursive(node->left);
|
||||
lsm_bt_node_free_tree(node->left);
|
||||
lsm_bt_node_free(node->left);
|
||||
}
|
||||
|
||||
if (node->right != NULL) {
|
||||
lsm_bt_node_free_recursive(node->right);
|
||||
lsm_bt_node_free_tree(node->right);
|
||||
lsm_bt_node_free(node->right);
|
||||
}
|
||||
|
||||
lsm_bt_node_free(node);
|
||||
}
|
||||
|
||||
lsm_error lsm_bt_init(lsm_bt **ptr) {
|
||||
|
|
@ -42,14 +42,23 @@ lsm_error lsm_bt_init(lsm_bt **ptr) {
|
|||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
void lsm_bt_free(lsm_bt *bt) {
|
||||
void lsm_bt_clear(lsm_bt *bt) {
|
||||
if (bt->root != NULL) {
|
||||
lsm_bt_node_free_recursive(bt->root);
|
||||
}
|
||||
lsm_bt_node_free_tree(bt->root);
|
||||
lsm_bt_node_free(bt->root);
|
||||
|
||||
bt->root = NULL;
|
||||
bt->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lsm_bt_free(lsm_bt *bt) {
|
||||
lsm_bt_clear(bt);
|
||||
free(bt);
|
||||
}
|
||||
|
||||
uint64_t lsm_bt_size(lsm_bt *bt) { return bt->size; }
|
||||
|
||||
lsm_error lsm_bt_insert(lsm_bt *bt, char key, void *data) {
|
||||
lsm_bt_node **dest = &bt->root;
|
||||
|
||||
|
|
@ -85,7 +94,9 @@ lsm_error lsm_bt_search(void **out, lsm_bt *bt, char key) {
|
|||
return lsm_error_not_found;
|
||||
}
|
||||
|
||||
*out = node->data;
|
||||
if (out != NULL) {
|
||||
*out = node->data;
|
||||
}
|
||||
|
||||
return lsm_error_ok;
|
||||
}
|
||||
|
|
@ -105,7 +116,9 @@ lsm_error lsm_bt_remove(void **out, lsm_bt *bt, char key) {
|
|||
return lsm_error_not_found;
|
||||
}
|
||||
|
||||
*out = (*dest)->data;
|
||||
if (out != NULL) {
|
||||
*out = (*dest)->data;
|
||||
}
|
||||
bt->size--;
|
||||
|
||||
if (((*dest)->left != NULL) && ((*dest)->right != NULL)) {
|
||||
|
|
@ -142,7 +155,10 @@ lsm_error lsm_bt_replace(void **out, lsm_bt *bt, char key, void *data) {
|
|||
return lsm_error_not_found;
|
||||
}
|
||||
|
||||
*out = node->data;
|
||||
if (out != NULL) {
|
||||
*out = node->data;
|
||||
}
|
||||
|
||||
node->data = data;
|
||||
|
||||
return lsm_error_ok;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ lsm_error lsm_trie_node_init(lsm_trie_node **ptr) {
|
|||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
void lsm_trie_node_free(lsm_trie_node *node) {
|
||||
lsm_bt_clear(&node->bt);
|
||||
lsm_str_zero(&node->skip);
|
||||
free(node);
|
||||
}
|
||||
|
||||
lsm_error lsm_trie_init(lsm_trie **ptr) {
|
||||
lsm_trie *trie = calloc(1, sizeof(lsm_trie));
|
||||
|
||||
|
|
@ -142,12 +148,14 @@ lsm_error lsm_trie_insert(lsm_trie *trie, lsm_str *key, void *data) {
|
|||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
lsm_error lsm_trie_search(void **data, lsm_trie *trie, lsm_str *key) {
|
||||
lsm_error lsm_trie_search(void **out, lsm_trie *trie, lsm_str *key) {
|
||||
uint64_t key_len = lsm_str_len(key);
|
||||
|
||||
if (key_len == 0) {
|
||||
if (trie->root->data != NULL) {
|
||||
*data = trie->root->data;
|
||||
if (out != NULL) {
|
||||
*out = trie->root->data;
|
||||
}
|
||||
|
||||
return lsm_error_ok;
|
||||
} else {
|
||||
|
|
@ -185,7 +193,80 @@ lsm_error lsm_trie_search(void **data, lsm_trie *trie, lsm_str *key) {
|
|||
return lsm_error_not_found;
|
||||
}
|
||||
|
||||
*data = node->data;
|
||||
if (out != NULL) {
|
||||
*out = node->data;
|
||||
}
|
||||
|
||||
return lsm_error_ok;
|
||||
}
|
||||
|
||||
lsm_error lsm_trie_remove(void **data, lsm_trie *trie, lsm_str *key) {
|
||||
uint64_t key_len = lsm_str_len(key);
|
||||
|
||||
if (key_len == 0) {
|
||||
if (trie->root->data != NULL) {
|
||||
if (data != NULL) {
|
||||
*data = trie->root->data;
|
||||
}
|
||||
|
||||
trie->root->data = NULL;
|
||||
trie->size--;
|
||||
|
||||
return lsm_error_ok;
|
||||
} else {
|
||||
return lsm_error_not_found;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t index = 0;
|
||||
lsm_trie_node *parent = trie->root;
|
||||
lsm_trie_node *child;
|
||||
lsm_error res;
|
||||
char c;
|
||||
|
||||
while (index < key_len) {
|
||||
c = lsm_str_char(key, index);
|
||||
res = lsm_bt_search((void **)&child, &parent->bt, c);
|
||||
|
||||
if (res != lsm_error_ok) {
|
||||
return res;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
uint64_t cmp = lsm_str_cmp(key, index, &child->skip, 0);
|
||||
|
||||
// If we end in the middle of an edge, we definitely haven't found the node
|
||||
if (cmp != lsm_str_len(&child->skip)) {
|
||||
return lsm_error_not_found;
|
||||
}
|
||||
|
||||
index += cmp;
|
||||
|
||||
// This context is needed for the removal
|
||||
if (index < key_len) {
|
||||
parent = child;
|
||||
}
|
||||
}
|
||||
|
||||
if (child->data == NULL) {
|
||||
return lsm_error_not_found;
|
||||
}
|
||||
|
||||
// Child is the node we wish to delete
|
||||
if (data != NULL) {
|
||||
*data = child->data;
|
||||
}
|
||||
|
||||
child->data = NULL;
|
||||
|
||||
// We only remove child if it has no children of its own
|
||||
if (lsm_bt_size(&child->bt) == 0) {
|
||||
lsm_bt_remove(NULL, &parent->bt, c);
|
||||
lsm_trie_node_free(child);
|
||||
}
|
||||
|
||||
trie->size--;
|
||||
|
||||
return lsm_error_ok;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue