Search/Sort

This commit is contained in:
2026-08-29 01:58:00 +08:00
parent 8e95904cc4
commit a0758766c5
56 changed files with 5425 additions and 0 deletions
+158
View File
@@ -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_NOTFOUND;
// 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;
}