C语言实现哈希表:解决数据存储与检索的高效利器

引子

当构造数组变得不实用或困难,尤其又要增删查找时。一种动态集合结构(至少支持INSERT、SEARCH和DELETE等字典操作)就被恨恨期待了——散列表就是一种实现字典操作的数据结构。

1. 初识哈希表

[[哈希]]表(Hash Table,又称散列表),可根据关键字(key)直接访问的数据结构。哈希表通过哈希函数把关键字映射到表中的一个位置,存储位置与关键字间产生一种对应关系 h ,使得每个 key 对应一个存储位置f(key)。查找时根据给定的关键字 key,通过f(key)确定包含key的记录在存储空间中的位置。

3. C语言实现

/*
 *@create: 2024-02-04
 *@authro: jytang@stu.ecnu.edu.cn
 *@descri: Hash Table实现
*/
/*---------- 头文件 -----------*/
#include <string.h>
/*---------- 宏定义 -----------*/
#define FAILURE (-1)
#define TRUE    (0)
#define FALSE   (1)
/*--------- 数据结构 ----------*/
typedef struct {
    char *key;
    int value;
    struct HashNode *next;
} HashNode;  // 哈希表节点

typedef struct {
    int tableSize;
    HashNode **table;
} HashTable;  // 哈希表结构
/*----------函数定义-----------*/
/*
 *@descri: 哈希函数
 *@parame: IN *key --键值
           IN table_size --哈希表大小
 *@return: 哈希值
*/
unsigned int HashFunction(const char *key, int table_size)
{
    unsigned int hash = 0;
    while (*key) {
        hash = (hash * 31) + *key;
        key++;
    }
    return hash % table_size;
}
/*
 *@descri: 创建哈希表
 *@parame: IN size --哈希表大小
 *@return: 哈希表指针
*/
HashTable *HashTable_Create(int size)
{
    HashTable *hashTable = (HashTable *)malloc(sizeof(HashTable));
    hashTable->tableSize = size;
    hashTable->table = (HashNode **)calloc(size, sizeof(HashNode *));
    return hashTable;
}
/*
 *@descri: 数据入槽
 *@parame: IN *hashTable --哈希表指针
 *@parame: IN *key --键值
 *@parame: IN size --哈希表大小
 *@return: 哈希表指针
*/
void HashTable_Insert(HashTable *hashTable, const char *key, int size)
{
    unsigned int index = HashFunction(key, hashTable->tableSize);
    HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
    newNode->key = _strdup(key);
    newNode->value = size;
    newNode->next = NULL;
    newNode->next = hashTable->table[index];
    hashTable->table[index] = newNode;
}
/*
 *@descri: 查找哈希表
 *@parame: IN *hashTable --哈希表指针
 *@parame: IN *key --键值
 *@return: 哈希表指针
*/
int HashTable_Search(HashTable *hashTable, const char *key)
{
    unsigned int index = HashFunction(key, hashTable->tableSize);
    HashNode *current = hashTable->table[index];
    while (current != NULL) {
        if (strcmp(current->key, key) == 0) {
            return current->value;
        }
        current = current->next;
    }
    return FAILURE;
}
/*
 *@descri: 数据出槽
 *@parame: IN *hashTable --哈希表指针
 *@parame: IN *key --键值
 *@return: 哈希表指针
*/
void HashTable_RemoveItem(HashTable *hashTable, const char *key)
{
    unsigned int index = HashFunction(key, hashTable->tableSize);
    HashNode *current = hashTable->table[index];
    HashNode *prev = NULL;
    // 遍历链表查找键
    while (current != NULL && strcmp(current->key, key) != 0) {
        prev = current;
        current = current->next;
    }
    // 如果找到键,删除节点
    if (current != NULL) {
        if (prev != NULL) {
            prev->next = current->next;
        } else {
            hashTable->table[index] = current->next;
        }
        free(current->key);
        free(current);
    }
}
/*
 *@descri: 销毁哈希表
 *@parame: IN *hashTable --哈希表指针
*/
void HashTable_Destroy(HashTable *hashTable)
{
    free(hashTable->table);
    free(hashTable);
}
/*
 *@descri: test
*/
int main(void)
{
    HashTable *hashTable = HashTable_Create(10);
    HashTable_Insert(hashTable, "apple", 5);
    HashTable_Insert(hashTable, "banana", 3);
    HashTable_Insert(hashTable, "orange", 8);
    printf("Value for key 'apple': %d\n", HashTable_Search(hashTable, "apple"));
    printf("Value for key 'banana': %d\n", HashTable_Search(hashTable, "banana"));
    printf("Value for key 'orange': %d\n", HashTable_Search(hashTable, "orange"));
    // 删除键为 "banana" 的节点
    HashTable_RemoveItem(hashTable, "banana");
    // 测试是否成功删除
    printf("Value for key 'banana': %d\n", HashTable_Search(hashTable, "banana"));
    HashTable_Destroy(hashTable);
  return 0;
}

参考

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平乾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值