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

C语言分离链接法哈希表Insert插入函数仅成功插入2个键原因排查

C语言哈希表插入失败问题修复

你的代码存在以下几处错误,导致仅部分键插入成功:

  • 节点存储类型与比较逻辑错误:struct ListNode的Element成员被定义为int类型,与你要存储的字符串指针类型不匹配。同时Find函数中直接使用!=比较Element和Key,本质是比较指针地址而非字符串内容,会出现大量误判。
  • 插入链表逻辑错误:采用头插法插入新节点时,没有给NewCell->Next赋值为原链表的首节点,直接将L->Next覆盖为新节点,导致同一个哈希槽中之前插入的节点被直接丢弃。
  • 语法错误:Insert函数返回值为void,但内存分配失败分支中写了return NULL,属于返回类型不匹配。
  • 表大小计算错误:main函数中计算表初始大小的逻辑错误,你当前得到的是单个人名数组的长度20,而非要存储的人名总数6,虽不直接导致插入失败,但会造成空间浪费。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#define MinTableSize 1

// 分离链接法解决哈希冲突
struct ListNode;
typedef struct ListNode *Position;
struct HashTbl;
typedef struct HashTbl *HashTable;

typedef unsigned int Index;

Index Hash(const char *Key, int Tablesize)
{
    unsigned int HashVal = 0;
    while (*Key != '\0')
    {
        HashVal += *Key++;
    }
    return HashVal % Tablesize;
}

struct ListNode
{
    // 修改为存储字符串指针
    const char *Element;
    Position Next;
};

typedef Position List;
struct HashTbl
{
    int TableSize;
    List *TheLists;
};

// 判断是否为素数
bool isPrime(int n)
{
    if (n <= 1)
    {
        return false;
    }

    if (n <= 3)
    {
        return true;
    }

    if (n % 2 == 0 || n % 3 == 0)
    {
        return false;
    }

    for (int i = 5; i * i <= n; i = i + 6)
    {
        if (n % i == 0 || n % (i + 2) == 0)
        {
            return false;
        }
    }
    return true;
}

// 查找下一个素数
int NextPrime(int N)
{
    if (N <= 1)
    {
        return 2;
    }
    int prime = N;
    bool found = false;

    while (!found)
    {
        prime++;
        if (isPrime(prime))
        {
            found = true;
        }
    }
    return prime;
}

// 初始化哈希表
HashTable InitializeTable(int TableSize)
{
    HashTable H;
    int i;
    if (TableSize < MinTableSize)
    {
        printf("Table size is too small\n");
        return NULL;
    }
    H = malloc(sizeof(struct HashTbl));
    if (H == NULL)
    {
        printf("Out of space\n");
        return NULL;
    }
    H->TableSize = NextPrime(TableSize);
    H->TheLists = malloc(sizeof(List) * H->TableSize);
    if (H->TheLists == NULL)
    {
        printf("Out of space\n");
        return NULL;
    }
    for (i = 0; i < H->TableSize; i++)
    {
        H->TheLists[i] = malloc(sizeof(struct ListNode));
        if (H->TheLists[i] == NULL)
        {
            printf("Out of space\n");
            return NULL;
        }
        else
        {
            H->TheLists[i]->Next = NULL;
        }
    }
    return H;
}

// 查找键
Position Find(const char *Key, HashTable H)
{
    Position P;
    List L;
    L = H->TheLists[Hash(Key, H->TableSize)];
    P = L->Next;
    // 修改为用strcmp比较字符串内容
    while (P != NULL && strcmp(P->Element, Key) != 0)
    {
        P = P->Next;
    }
    return P;
}

// 插入键
void Insert(const char *Key, HashTable H)
{
    Position Pos;
    Position NewCell;
    List L;
    Pos = Find(Key, H);
    if (Pos == NULL)
    {
        NewCell = malloc(sizeof(struct ListNode));
        if (NewCell == NULL)
        {
            printf("Out of space\n");
            // 修正返回值错误,void函数不需要返回值
            return;
        }
        else
        {
            L = H->TheLists[Hash(Key, H->TableSize)];
            // 修正头插法逻辑,先将新节点的next指向原首节点
            NewCell->Next = L->Next;
            NewCell->Element = Key;
            L->Next = NewCell;
            printf("Key %s inserted\n", Key);
        }
    }
    else
    {
        printf("Key %s already exist\n", Key);
    }
}

int main()
{
    char Name[6][20] = { "Joshua", "Erica", "Elizabeth", "Monica", "Jefferson", "Andrian" };
    // 修正表大小计算,获取名字总数6
    int Size = sizeof(Name) / sizeof(Name[0]);
    HashTable H = InitializeTable(Size);

    Insert(Name[0], H);
    Insert(Name[1], H);
    Insert(Name[2], H);
    Insert(Name[3], H);
    Insert(Name[4], H);
    Insert(Name[5], H);

    return 0;
}

运行结果

修正后所有6个人名都会正常插入,输出如下:

Key Joshua inserted
Key Erica inserted
Key Elizabeth inserted
Key Monica inserted
Key Jefferson inserted
Key Andrian inserted

内容的提问来源于stack exchange,提问作者Maria Marchella Gandhi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 22:06:00