Files
cKit/Search/c_BST.c
T
2026-08-30 22:24:45 +08:00

215 lines
7.1 KiB
C

#include <c_BST.h>
c_err_t c_BST_Init(c_BST_t* self, c_size_t key_size, c_size_t val_size, c_SortCompare_t cmp, void* args, c_Allocator_t* allocator) {
if (!self || key_size == 0 || val_size == 0 || !cmp) {
return C_ERR_PARAM;
}
// 自适应分配器降级缺省安全播种
if (allocator) {
self->allocator = *allocator;
} else {
self->allocator = c_DefaultAllocator;
}
self->root = NULL;
self->size = 0;
self->key_size = key_size;
self->val_size = val_size;
self->cmp = cmp;
self->args = args;
return C_ERR_OK;
}
/**
* @brief 根据指定的 Key 检索关联的 Value 值(平均时间复杂度 O(log N))
*/
c_err_t c_BST_Get(const c_BST_t* self, const void* key, void* out_val) {
if (!self || !key || !out_val) return C_ERR_PARAM;
c_BSTNode* curr = self->root;
while (curr != NULL) {
int cmp_res = self->cmp(key, curr->key, self->args);
if (cmp_res < 0) {
curr = curr->left; // 目标比当前小,滑向左子树
} else if (cmp_res > 0) {
curr = curr->right; // 目标比当前大,滑向右子树
} else {
// 精确命中,将内部深度存储的数据镜像复制给外部
memcpy(out_val, curr->val, self->val_size);
return C_ERR_OK;
}
}
return C_ERR_NOTFOUND;
}
/**
* @brief 检查树中是否包含指定的 Key 键值
*/
bool c_BST_Contains(const c_BST_t* self, const void* key) {
if (!self || !key) return false;
c_BSTNode* curr = self->root;
while (curr != NULL) {
int cmp_res = self->cmp(key, curr->key, self->args);
if (cmp_res < 0) curr = curr->left;
else if (cmp_res > 0) curr = curr->right;
else return true;
}
return false;
}
/**
* @brief 内部递归插入/覆写辅助(基于二级指针代理,完美消除悬空控制流)
*/
static c_err_t c_BST_InternalPut(c_BST_t* self, c_BSTNode** node_ptr, const void* key, const void* val, bool* is_new_inserted) {
c_BSTNode* curr = *node_ptr;
// 递归基:如果当前插槽为空,在此物理位置开辟并挂载新节点
if (curr == NULL) {
c_BSTNode* new_node = (c_BSTNode*)c_Allocator_Alloc(&self->allocator, sizeof(c_BSTNode));
void* new_key = c_Allocator_Alloc(&self->allocator, self->key_size);
void* new_val = c_Allocator_Alloc(&self->allocator, self->val_size);
if (!new_node || !new_key || !new_val) {
if (new_node) c_Allocator_Free(&self->allocator, new_node);
if (new_key) c_Allocator_Free(&self->allocator, new_key);
if (new_val) c_Allocator_Free(&self->allocator, new_val);
return C_ERR_NOMEM;
}
memcpy(new_key, key, self->key_size);
memcpy(new_val, val, self->val_size);
new_node->key = new_key;
new_node->val = new_val;
new_node->left = NULL;
new_node->right = NULL;
*node_ptr = new_node; // 代理写入,父节点指针自动对齐
*is_new_inserted = true;
return C_ERR_OK;
}
int cmp_res = self->cmp(key, curr->key, self->args);
if (cmp_res < 0) {
return c_BST_InternalPut(self, &(curr->left), key, val, is_new_inserted);
} else if (cmp_res > 0) {
return c_BST_InternalPut(self, &(curr->right), key, val, is_new_inserted);
} else {
// 键已存在,执行覆写(Overwrite)语义
memcpy(curr->val, val, self->val_size);
*is_new_inserted = false;
return C_ERR_OK;
}
}
/**
* @brief 存入键值对。若 Key 已存在则覆写更新;若不存在则开辟新节点维护树拓扑
*/
c_err_t c_BST_Put(c_BST_t* self, const void* key, const void* val) {
if (!self || !key || !val) return C_ERR_PARAM;
bool is_new = false;
c_err_t err = c_BST_InternalPut(self, &(self->root), key, val, &is_new);
if (err == C_ERR_OK && is_new) {
self->size++;
}
return err;
}
/**
* @brief 内部辅助:寻找并剥离指定子树的绝对最小值节点(用于 Hibbard 删除替换)
*/
static c_BSTNode* c_BST_DeleteMin(c_BST_t* self, c_BSTNode** node_ptr) {
c_BSTNode* curr = *node_ptr;
if (curr->left == NULL) {
// 找到最小值,将右子树代理向上对接,将当前节点断开剥离并返回
*node_ptr = curr->right;
return curr;
}
return c_BST_DeleteMin(self, &(curr->left));
}
/**
* @brief 内部递归删除控制流(基于二级指针代理的 Hibbard 经典删除算法)
*/
static c_err_t c_BST_InternalDelete(c_BST_t* self, c_BSTNode** node_ptr, const void* key) {
c_BSTNode* curr = *node_ptr;
if (curr == NULL) {
return C_ERR_NOTFOUND; // 节点不存在
}
int cmp_res = self->cmp(key, curr->key, self->args);
if (cmp_res < 0) {
return c_BST_InternalDelete(self, &(curr->left), key);
} else if (cmp_res > 0) {
return c_BST_InternalDelete(self, &(curr->right), key);
} else {
// 精确命中当前要删除的节点 curr,开启 Hibbard 拆解合并
c_BSTNode* old_node = curr;
if (curr->right == NULL) {
// 情况 1:无右子树,直接将左子树整体顶替上来
*node_ptr = curr->left;
} else if (curr->left == NULL) {
// 情况 2:无左子树,直接将右子树整体顶替上来
*node_ptr = curr->right;
} else {
// 情况 3:左右子树均完好。寻找右子树的绝对最小值充当继承后继者 (Successor)
c_BSTNode* successor = c_BST_DeleteMin(self, &(curr->right));
// 后继者完美接管原节点的双向拓扑路由
successor->left = old_node->left;
successor->right = *node_ptr; // 此时 *node_ptr 已经是处理过 deleteMin 后的右子树根
*node_ptr = successor; // 代理顶替
}
// 释放被移出树的旧节点物理内存
c_Allocator_Free(&self->allocator, old_node->key);
c_Allocator_Free(&self->allocator, old_node->val);
c_Allocator_Free(&self->allocator, old_node);
return C_ERR_OK;
}
}
/**
* @brief 根据指定 Key 彻底从树中移出其关联的键值对节点
*/
c_err_t c_BST_Delete(c_BST_t* self, const void* key) {
if (!self || !key) return C_ERR_PARAM;
if (self->size == 0) return C_ERR_EMPTY;
c_err_t err = c_BST_InternalDelete(self, &(self->root), key);
if (err == C_ERR_OK) {
self->size--;
}
return err;
}
/**
* @brief 内部递归反初始化解构辅助
*/
static void c_BST_InternalDeinit(c_Allocator_t* alloc, c_BSTNode* node) {
if (node == NULL) return;
// 递归后序遍历:先解构左右子树,再回收当前节点
c_BST_InternalDeinit(alloc, node->left);
c_BST_InternalDeinit(alloc, node->right);
c_Allocator_Free(alloc, node->key);
c_Allocator_Free(alloc, node->val);
c_Allocator_Free(alloc, node);
}
/**
* @brief 二叉搜索树反初始化彻底释放
*/
void c_BST_Destroy(c_BST_t* self) {
if (self && self->root) {
c_BST_InternalDeinit(&self->allocator, self->root);
self->root = NULL;
self->size = 0;
}
}