Files
cKit/Search/c_SeqSearchST.c
T

150 lines
4.5 KiB
C
Raw Normal View History

2026-08-30 22:24:45 +08:00
#include <c_SeqSearchST.h>
c_err_t c_SeqSearchST_Init(c_SeqSearchST_t* self, c_size_t key_size, c_size_t val_size, c_SortCompare_t key_cmp, void* args, c_Allocator_t* allocator) {
if (!self || key_size == 0 || val_size == 0 || !key_cmp) {
return C_ERR_PARAM;
}
// 自适应分配器降级缺省安全播种
if (allocator) {
self->allocator = *allocator;
} else {
self->allocator = c_DefaultAllocator;
}
self->first = NULL;
self->size = 0;
self->key_size = key_size;
self->val_size = val_size;
self->key_cmp = key_cmp;
self->args = args;
return C_ERR_OK;
}
/**
* @brief 存入键值对。若 Key 已存在则覆写更新其 Value;若不存在则使用头插法压入新节点
*/
c_err_t c_SeqSearchST_Put(c_SeqSearchST_t* self, const void* key, const void* val) {
if (!self || !key || !val) return C_ERR_PARAM;
// 1. 前置顺序走查:如果键值已经存在,直接更新它的值(覆写语义)
for (c_SeqSearchSTNode* x = self->first; x != NULL; x = x->next) {
if (self->key_cmp(key, x->key, self->args) == 0) {
memcpy(x->val, val, self->val_size);
return C_ERR_OK;
}
}
// 2. 键值不存在,启动托管分配:开辟新节点以及键和值的独立存储块
c_SeqSearchSTNode* new_node = (c_SeqSearchSTNode*)c_Allocator_Alloc(&self->allocator, sizeof(c_SeqSearchSTNode));
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;
// 3. 头插法挂载新节点
new_node->next = self->first;
self->first = new_node;
self->size++;
return C_ERR_OK;
}
/**
* @brief 根据指定的 Key 检索关联的 Value 值
*/
c_err_t c_SeqSearchST_Get(const c_SeqSearchST_t* self, const void* key, void* out_val) {
if (!self || !key || !out_val) return C_ERR_PARAM;
for (const c_SeqSearchSTNode* x = self->first; x != NULL; x = x->next) {
if (self->key_cmp(key, x->key, self->args) == 0) {
memcpy(out_val, x->val, self->val_size);
return C_ERR_OK;
}
}
return C_ERR_NOTFOUND;
}
/**
* @brief 检查符号表内是否包含指定的 Key 键值
*/
bool c_SeqSearchST_Contains(const c_SeqSearchST_t* self, const void* key) {
if (!self || !key) return false;
for (const c_SeqSearchSTNode* x = self->first; x != NULL; x = x->next) {
if (self->key_cmp(key, x->key, self->args) == 0) {
return true;
}
}
return false;
}
/**
* @brief 根据指定 Key 彻底从符号表中移出其关联的键值对节点
*/
c_err_t c_SeqSearchST_Delete(c_SeqSearchST_t* self, const void* key) {
if (!self || !key) return C_ERR_PARAM;
if (self->size == 0) return C_ERR_EMPTY;
c_SeqSearchSTNode* prev = NULL;
c_SeqSearchSTNode* curr = self->first;
while (curr != NULL) {
if (self->key_cmp(key, curr->key, self->args) == 0) {
if (prev == NULL) {
self->first = curr->next;
} else {
prev->next = curr->next;
}
// 原路回收释放单节点下深开辟的所有子内存块
c_Allocator_Free(&self->allocator, curr->key);
c_Allocator_Free(&self->allocator, curr->val);
c_Allocator_Free(&self->allocator, curr);
self->size--;
return C_ERR_OK;
}
prev = curr;
curr = curr->next;
}
return C_ERR_NOTFOUND;
}
/**
* @brief 反初始化:深度级联释放符号表内的所有节点、键和值的全部堆空间
*/
void c_SeqSearchST_Destroy(c_SeqSearchST_t* self) {
if (!self) return;
c_SeqSearchSTNode* curr = self->first;
while (curr != NULL) {
c_SeqSearchSTNode* next_tmp = curr->next;
c_Allocator_Free(&self->allocator, curr->key);
c_Allocator_Free(&self->allocator, curr->val);
c_Allocator_Free(&self->allocator, curr);
curr = next_tmp;
}
self->first = NULL;
self->size = 0;
}