You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C的链地址法哈希表搜索函数返回错误值问题排查

链地址法哈希表搜索异常问题排查

我在算法课程作业中用C语言实现链地址法哈希表,哈希函数采用基于Knuth常数((√5)-1)/2的乘法哈希,键的哈希计算确认正确,但调用搜索函数时,返回值和插入时的预期不符。想排查下Node**数组的使用是否存在错误,以下是我的实现代码:

初始化哈希表

void * AllocateChainTable(int elementCountMax)
{
    Node ** array = calloc(elementCountMax, sizeof(Node *));
    for (int i = 0; i < elementCountMax; i++) {
        array[i] = initList();

    }
    return array;
}

插入函数

int InsertChain(    void * hashtable, int elementSize, int elementCountMax,
                            int key, void * element, int (*HashFunc)(int key))
{
    Node ** hashTable = hashtable;
    int hashedKey = HashFunc(key);
    insertAtHead(hashTable[hashedKey], element, key);
    return 0;
}

链表头插函数(带哑节点)

void insertAtHead(Node * node, void * data, int key) {
    int error = 0;
    Node * new = createNode(data, &error, key);
    if (error == 1) {
        return;
    }
    if (node->next == NULL) {
        node->next = new;
        int * size = (int *)node->data;
        *size++;
        return;
    }
    Node * oldHead = node->next->next;
    node->next = new;
    new->next = oldHead;
    int * size = (int *)node->data;
    *size++;
}

搜索函数

void * SearchChain(void * hashtable, int key, int elementSize, int (*HashFunc)(int key))
{
    Node ** hashTable = hashtable;
    int hashKey = HashFunc(key);
    if (hashTable[hashKey]->next != NULL) {
        Node * startingNode = hashTable[hashKey]->next;
        while (startingNode != NULL) {
            if (startingNode->key == key) {
                return startingNode->data;
            }
            else {
                startingNode = startingNode->next;
            }
        }
    }
    return NULL;
}

问题排查结论

Node**数组的使用本身没有错误,问题出在insertAtHead函数的实现上:

  1. 头插逻辑错误:
    原代码中Node * oldHead = node->next->next;会跳过当前链表的第一个有效节点,导致新插入的节点直接连接到第二个有效节点之后,第一个节点丢失。正确的头插应该保存当前的头节点node->next,再将新节点的next指向这个旧头节点。
  2. size自增操作错误:
    *size++;因运算符优先级问题,实际执行的是*(size++),只会移动指针而不会修改原size变量的值,正确写法应为(*size)++;,先解引用再自增。

修正后的insertAtHead函数

void insertAtHead(Node * node, void * data, int key) {
    int error = 0;
    Node * new = createNode(data, &error, key);
    if (error == 1) {
        return;
    }
    // 保存原有头节点,完成头插
    Node * oldHead = node->next;
    node->next = new;
    new->next = oldHead;
    // 正确更新链表大小
    int * size = (int *)node->data;
    (*size)++;
}

内容的提问来源于stack exchange,提问作者QuantumBlink

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:40:25