开始设计
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
#include <c_BST.h>
|
||||
#include <c_Memory.h>
|
||||
|
||||
/**
|
||||
* Helper accessors to safely locate key and value buffers within a generic node allocation block.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE void* c_BST_NodeKey(c_BSTNode_t* node) {
|
||||
return (void*)((char*)node + sizeof(c_BSTNode_t));
|
||||
}
|
||||
|
||||
C_STATIC_FORCE_INLINE void* c_BST_NodeVal(c_BSTNode_t* node, c_size_t key_size) {
|
||||
return (void*)((char*)node + sizeof(c_BSTNode_t) + key_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and initializes a standalone tree node layout.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_BSTNode_t* c_BST_CreateNode(const void* key, const void* val, c_size_t ks, c_size_t vs) {
|
||||
c_BSTNode_t* node = (c_BSTNode_t*)C_ALLOC(sizeof(c_BSTNode_t) + ks + vs);
|
||||
if (node == NULL) return NULL;
|
||||
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
memcpy(c_BST_NodeKey(node), key, ks);
|
||||
memcpy(c_BST_NodeVal(node, ks), val, vs);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal recursive post-order destructor helper.
|
||||
*/
|
||||
static void c_BST_DestroyNodes(c_BSTNode_t* node) {
|
||||
if (node == NULL) return;
|
||||
c_BST_DestroyNodes(node->left);
|
||||
c_BST_DestroyNodes(node->right);
|
||||
C_FREE(node);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
c_err_t c_BST_Init(c_BST_t* tree, c_size_t key_size, c_size_t val_size, int (*compar)(const void*, const void*)) {
|
||||
if (tree == NULL || key_size == 0 || val_size == 0 || compar == NULL) return C_ERR_PARAM;
|
||||
tree->root = NULL;
|
||||
tree->key_size = key_size;
|
||||
tree->val_size = val_size;
|
||||
tree->size = 0;
|
||||
tree->compar = compar;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
void c_BST_Destroy(c_BST_t* tree) {
|
||||
if (tree) {
|
||||
c_BST_DestroyNodes(tree->root);
|
||||
tree->root = NULL;
|
||||
tree->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
c_err_t c_BST_Clear(c_BST_t* tree) {
|
||||
if (tree == NULL) return C_ERR_PARAM;
|
||||
c_BST_DestroyNodes(tree->root);
|
||||
tree->root = NULL;
|
||||
tree->size = 0;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
c_bool_t c_BST_Contains(const c_BST_t* tree, const void* key) {
|
||||
if (tree == NULL || key == NULL) return C_FALSE;
|
||||
c_BSTNode_t* curr = tree->root;
|
||||
while (curr != NULL) {
|
||||
int cmp = tree->compar(key, c_BST_NodeKey(curr));
|
||||
if (cmp == 0) return C_TRUE;
|
||||
curr = (cmp < 0) ? curr->left : curr->right;
|
||||
}
|
||||
return C_FALSE;
|
||||
}
|
||||
|
||||
c_err_t c_BST_Put(c_BST_t* tree, const void* key, const void* val) {
|
||||
if (tree == NULL || key == NULL || val == NULL) return C_ERR_PARAM;
|
||||
|
||||
c_BSTNode_t** link = &tree->root;
|
||||
c_BSTNode_t* curr = tree->root;
|
||||
|
||||
while (curr != NULL) {
|
||||
int cmp = tree->compar(key, c_BST_NodeKey(curr));
|
||||
if (cmp == 0) {
|
||||
// Overwrite existing value for matching symbol key
|
||||
memcpy(c_BST_NodeVal(curr, tree->key_size), val, tree->val_size);
|
||||
return C_ERR_OK;
|
||||
}
|
||||
link = (cmp < 0) ? &curr->left : &curr->right;
|
||||
curr = *link;
|
||||
}
|
||||
|
||||
// Key is unique, construct a new node configuration structure
|
||||
c_BSTNode_t* new_node = c_BST_CreateNode(key, val, tree->key_size, tree->val_size);
|
||||
if (new_node == NULL) return C_ERR_NOMEM;
|
||||
|
||||
*link = new_node;
|
||||
tree->size++;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
void* c_BST_Get(const c_BST_t* tree, const void* key) {
|
||||
if (tree == NULL || key == NULL) return NULL;
|
||||
c_BSTNode_t* curr = tree->root;
|
||||
while (curr != NULL) {
|
||||
int cmp = tree->compar(key, c_BST_NodeKey(curr));
|
||||
if (cmp == 0) return c_BST_NodeVal(curr, tree->key_size);
|
||||
curr = (cmp < 0) ? curr->left : curr->right;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c_err_t c_BST_Delete(c_BST_t* tree, const void* key) {
|
||||
if (tree == NULL || key == NULL) return C_ERR_PARAM;
|
||||
|
||||
c_BSTNode_t** link = &tree->root;
|
||||
c_BSTNode_t* curr = tree->root;
|
||||
|
||||
while (curr != NULL) {
|
||||
int cmp = tree->compar(key, c_BST_NodeKey(curr));
|
||||
if (cmp == 0) break;
|
||||
link = (cmp < 0) ? &curr->left : &curr->right;
|
||||
curr = *link;
|
||||
}
|
||||
|
||||
if (curr == NULL) return C_ERR_NOT_FOUND;
|
||||
|
||||
// Standard Hibbard deletion implementation sequence matching tree boundaries
|
||||
if (curr->left == NULL) {
|
||||
*link = curr->right;
|
||||
} else if (curr->right == NULL) {
|
||||
*link = curr->left;
|
||||
} else {
|
||||
// Node has two children; locate the successor node (smallest node in the right sub-tree)
|
||||
c_BSTNode_t** succ_link = &curr->right;
|
||||
c_BSTNode_t* succ = curr->right;
|
||||
while (succ->left != NULL) {
|
||||
succ_link = &succ->left;
|
||||
succ = succ->left;
|
||||
}
|
||||
|
||||
// Delink the successor node from its previous position
|
||||
*succ_link = succ->right;
|
||||
|
||||
// Route child structures of the node being deleted into the successor
|
||||
succ->left = curr->left;
|
||||
succ->right = curr->right;
|
||||
*link = succ;
|
||||
}
|
||||
|
||||
C_FREE(curr);
|
||||
tree->size--;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user