Working on removing keys from B+ trees
This commit is contained in:
5
.idea/vcs.xml
generated
5
.idea/vcs.xml
generated
@@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="CommitMessageInspectionProfile">
|
||||||
|
<profile version="1.0">
|
||||||
|
<inspection_tool class="SubjectBodySeparation" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
104
src/bplus_tree.c
104
src/bplus_tree.c
@@ -91,6 +91,28 @@ bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bplus_node_remove_kv(BPlusNode *node, BPlusKV *kv) {
|
||||||
|
bool removed = false;
|
||||||
|
//Find key
|
||||||
|
for (size_t i = 0; i < node->keyCount; i++) {
|
||||||
|
if (node->keys[i] == kv) {
|
||||||
|
node->keys[i] = NULL;
|
||||||
|
node->keyCount--;
|
||||||
|
//Move keys down
|
||||||
|
for (; i < node->keyCount; i++) {
|
||||||
|
node->keys[i] = node->keys[i + 1];
|
||||||
|
}
|
||||||
|
removed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bplus_node_merge(BPlusNode *left, BPlusNode *right) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void print_bplus_node(BPlusNode *node, size_t indent) {
|
void print_bplus_node(BPlusNode *node, size_t indent) {
|
||||||
char *indentStr = calloc(indent + 1, sizeof(char));
|
char *indentStr = calloc(indent + 1, sizeof(char));
|
||||||
memset(indentStr, ' ', sizeof(char) * indent);
|
memset(indentStr, ' ', sizeof(char) * indent);
|
||||||
@@ -213,7 +235,7 @@ BPlusNode *bplus_tree_find_leaf(BPlusTree *tree, uint64_t key) {
|
|||||||
|
|
||||||
bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
|
bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
|
||||||
BPlusNode *node = bplus_tree_find_leaf(tree, newKey);
|
BPlusNode *node = bplus_tree_find_leaf(tree, newKey);
|
||||||
assert(node != NULL);
|
assert(node != NULL && node->isInternal == false);
|
||||||
|
|
||||||
if (node->keyCount < node->order - 1) {
|
if (node->keyCount < node->order - 1) {
|
||||||
//Can insert at this node
|
//Can insert at this node
|
||||||
@@ -294,6 +316,86 @@ bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bplus_tree_delete(BPlusTree *tree, uint64_t key) {
|
||||||
|
BPlusNode *node = bplus_tree_find_leaf(tree, key);
|
||||||
|
assert(node != NULL && node->isInternal == false);
|
||||||
|
|
||||||
|
//Find and remove kv
|
||||||
|
bool removed = false;
|
||||||
|
for (size_t i = 0; i < node->keyCount; i++) {
|
||||||
|
if (node->keys[i]->key == key) {
|
||||||
|
BPlusKV *kv = node->keys[i];
|
||||||
|
removed = bplus_node_remove_kv(node, node->keys[i]);
|
||||||
|
assert(removed);
|
||||||
|
free_bplus_kv(kv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->keyCount >= tree->minFill || node->parent == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Try and borrow a key from a neighbour
|
||||||
|
|
||||||
|
//Check right leaf
|
||||||
|
if (node->rightLeaf != NULL
|
||||||
|
&& node->rightLeaf->parent == node->parent
|
||||||
|
&& node->rightLeaf->keyCount > tree->minFill) {
|
||||||
|
//Move first kv on leaf to this node
|
||||||
|
BPlusKV *kv = node->rightLeaf->keys[0];
|
||||||
|
assert(bplus_node_remove_kv(node->rightLeaf, kv));
|
||||||
|
assert(bplus_node_insert_kv(node, kv));
|
||||||
|
//Update the right leafs parent pointer
|
||||||
|
for (size_t i = 0; i < node->parent->keyCount; i++) {
|
||||||
|
if (node->parent->keys[i]->rightPointer == node->rightLeaf) {
|
||||||
|
node->parent->keys[i]->key = node->rightLeaf->keys[0]->key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check left leaf
|
||||||
|
if (node->leftLeaf != NULL
|
||||||
|
&& node->leftLeaf->parent == node->parent
|
||||||
|
&& node->leftLeaf->keyCount > tree->minFill) {
|
||||||
|
//Borrow right most key from left leaf
|
||||||
|
BPlusKV *kv = node->leftLeaf->keys[node->keyCount - 1];
|
||||||
|
assert(bplus_node_remove_kv(node->leftLeaf, kv));
|
||||||
|
assert(bplus_node_insert_kv(node, kv));
|
||||||
|
//Update the key pointing to this node
|
||||||
|
for (size_t i = 0; i < node->parent->keyCount; i++) {
|
||||||
|
if (node->parent->keys[i]->rightPointer == node) {
|
||||||
|
node->parent->keys[i]->key = node->keys[0]->key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//No key to borrow, merge with a sibling
|
||||||
|
//Look right and left for leafs with same parent and where merging would result in keys < order
|
||||||
|
|
||||||
|
//Try right leaf
|
||||||
|
if (node->rightLeaf != NULL
|
||||||
|
&& node->parent == node->rightLeaf->parent
|
||||||
|
&& node->keyCount + node->rightLeaf->keyCount < tree->order) {
|
||||||
|
return bplus_node_merge(node, node->rightLeaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Try left leaf
|
||||||
|
if (node->leftLeaf != NULL
|
||||||
|
&& node->parent == node->leftLeaf->parent
|
||||||
|
&& node->keyCount + node->leftLeaf->keyCount < tree->order) {
|
||||||
|
return bplus_node_merge(node->leftLeaf, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
BPlusKV *bplus_tree_find(BPlusTree *tree, uint64_t key) {
|
BPlusKV *bplus_tree_find(BPlusTree *tree, uint64_t key) {
|
||||||
BPlusNode *leaf = bplus_tree_find_leaf(tree, key);
|
BPlusNode *leaf = bplus_tree_find_leaf(tree, key);
|
||||||
if (leaf == NULL) {
|
if (leaf == NULL) {
|
||||||
|
|||||||
@@ -41,9 +41,13 @@ void free_bplus_node(BPlusNode *node);
|
|||||||
|
|
||||||
bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv);
|
bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv);
|
||||||
|
|
||||||
|
bool bplus_node_remove_kv(BPlusNode *node, BPlusKV *kv);
|
||||||
|
|
||||||
|
bool bplus_node_merge(BPlusNode *left, BPlusNode *right);
|
||||||
|
|
||||||
void print_bplus_node(BPlusNode *node, size_t indent);
|
void print_bplus_node(BPlusNode *node, size_t indent);
|
||||||
|
|
||||||
char * debug_bplus_node_str(BPlusNode *node, char *str, size_t *strSize);
|
char *debug_bplus_node_str(BPlusNode *node, char *str, size_t *strSize);
|
||||||
|
|
||||||
struct BPlusTree_t {
|
struct BPlusTree_t {
|
||||||
size_t order;
|
size_t order;
|
||||||
@@ -58,13 +62,16 @@ BPlusTree *new_bplus_tree(size_t order);
|
|||||||
void free_bplus_tree(BPlusTree *tree);
|
void free_bplus_tree(BPlusTree *tree);
|
||||||
|
|
||||||
void print_bplus_tree(BPlusTree *tree);
|
void print_bplus_tree(BPlusTree *tree);
|
||||||
|
|
||||||
char *debug_bplus_tree_str(BPlusTree *tree, char *str);
|
char *debug_bplus_tree_str(BPlusTree *tree, char *str);
|
||||||
|
|
||||||
BPlusNode * bplus_tree_find_leaf(BPlusTree *tree, uint64_t key);
|
BPlusNode *bplus_tree_find_leaf(BPlusTree *tree, uint64_t key);
|
||||||
|
|
||||||
bool bplus_tree_insert(BPlusTree *tree, uint64_t key, void *value);
|
bool bplus_tree_insert(BPlusTree *tree, uint64_t key, void *value);
|
||||||
|
|
||||||
BPlusKV * bplus_tree_find(BPlusTree *tree, uint64_t key);
|
bool bplus_tree_delete(BPlusTree *tree, uint64_t key);
|
||||||
|
|
||||||
|
BPlusKV *bplus_tree_find(BPlusTree *tree, uint64_t key);
|
||||||
|
|
||||||
enum BPlusFindComp_t {
|
enum BPlusFindComp_t {
|
||||||
FIND_NONE = 0,
|
FIND_NONE = 0,
|
||||||
@@ -73,6 +80,7 @@ enum BPlusFindComp_t {
|
|||||||
FIND_GT = 4
|
FIND_GT = 4
|
||||||
};
|
};
|
||||||
typedef enum BPlusFindComp_t BPlusFindComp;
|
typedef enum BPlusFindComp_t BPlusFindComp;
|
||||||
BPlusKV * bplus_tree_find_closest(BPlusTree *tree, uint64_t key, BPlusFindComp dir);
|
|
||||||
|
BPlusKV *bplus_tree_find_closest(BPlusTree *tree, uint64_t key, BPlusFindComp dir);
|
||||||
|
|
||||||
#endif //SDB_BPLUS_TREE_H
|
#endif //SDB_BPLUS_TREE_H
|
||||||
|
|||||||
Reference in New Issue
Block a user