哈希表的设计与实现

简介: 哈希表的设计与实现

本文详细介绍了哈希表的数据结构,包括键值对的定义、如何通过哈希函数确定数组下标、以及如何使用链地址法解决哈希冲突。还涵盖了插入、查找和删除操作,以及哈希表的完整生命周期管理。

摘要由CSDN通过智能技术生成

哈希表实现了“键key——值value”这一映射关系的存储。每个值对应唯一的键,一个键可以对应多个值

哈希表在插入、删除、查找一个元素都只需要O(1)的时间复杂度,所以哈希表常常用来优化时间效率,在基础数据结构中,数组满足O(1)时间复杂度,所以哈希表可以考虑使用‘数组’实现。

由于每个值唯一对应一个键,需要通过键来查找特定的值,因此一个值和它唯一对应的键是同时存储的,称为‘键值对’。下图定义了一个键值对结构体:

//定义哈希表的节点结构(叫节点是因为键值对用链表存储在数组中)
typedef struct HashNode {
    char* key;
    int value;
    struct HashNode* next; // 指向下一个节点的指针,用来解决哈希冲突
} HashNode;

所以在数组中存储‘键值对’时,使用‘’来确定键值对在数组中的下标

下图为数组实现的哈希表结构:

// 哈希表结构
typedef struct {
    HashNode* array[TABLE_SIZE]; // 哈希表的桶数组
} HashTable;

将键转换成数组下标的过程:将键转换成整数(即哈希值),哈希值对数组长度求余,得到的余数为数组的下标。

键如果是英文或中文字符,则通过ASCII或Unicode转换成整数(即哈希值)。

// 哈希函数,这里简单地将键转换为整数然后取余
int hash(char* key) {
    int hashValue = 0;
    int len = strlen(key);
    for (int i = 0; i < len; i++) {
        hashValue = (hashValue << 5) + key[i];
    }
    return hashValue % TABLE_SIZE;
}

因此这样的转换方式会出现多个键具有相同的哈希值,即出现多个键值对需要存储到数组的同一个位置,很显然这会引起冲突,叫做哈希冲突

// 创建哈希表
HashTable* createHashTable() {
    HashTable* hashtable = (HashTable*)malloc(sizeof(HashTable));
    for (int i = 0; i < TABLE_SIZE; i++) {
        hashtable->array[i] = NULL;
    }
    return hashtable;
}

为了解决哈希冲突,可以把存入数组中同一位置的多个键值对用链表存储,也就是说,数组中每个位置存储的是链表。

// 插入键值对到哈希表,采用链地址法解决冲突
void insert(HashTable* hashtable, char* key, int value) {
    int index = hash(key);//哈希值
    HashNode* newNode = (HashNode*)malloc(sizeof(HashNode));//为新键值对创建新节点
    newNode->key = strdup(key);
    newNode->value = value;
    newNode->next = NULL;//初始化结点指针
    if (hashtable->array[index] == NULL) {//哈希表上所要插入的位置为空(无链表)
        hashtable->array[index] = newNode;
    } else {                              //不为空,出现冲突
        HashNode* current = hashtable->array[index];//声明当前节点指针
        while (current->next != NULL) {//遍历到该位置链表的最后一个节点
            current = current->next;//找到了最后一个节点,并将当前节点设置为最后一个节点
        }
        current->next = newNode;//将最后一个节点的next指针从NULL设置为newnode新节点
    }
}
查找:
 
// 根据键查找对应的值
int get(HashTable* hashtable, char* key) {
    int index = hash(key);
    HashNode* current = hashtable->array[index];
    while (current != NULL) {
        if (strcmp(current->key, key) == 0) {
            return current->value;
        }
        current = current->next;
    }
    return -1; // 表示未找到
}
删除:
 
// 从哈希表中删除指定键的键值对
void removeKey(HashTable* hashtable, char* key) {
    int index = hash(key);
    HashNode* current = hashtable->array[index];
    HashNode* prev = NULL;
    // 查找要删除的节点并记录其前驱节点
    while (current != NULL && strcmp(current->key, key) != 0) {
        prev = current;
        current = current->next;
    }
    // 如果找到了要删除的节点
    if (current != NULL) {
        // 如果要删除的节点是链表的第一个节点
        if (prev == NULL) {
            hashtable->array[index] = current->next;
        } else {
            prev->next = current->next;
        }
        // 释放要删除的节点的内存
        free(current->key);
        free(current);
    }
}
完全销毁哈希表(销毁哈希表中所有占用内存的子成员):
 
// 销毁哈希表
void destroyHashTable(HashTable* hashtable) {
    for (int i = 0; i < TABLE_SIZE; i++) {
        HashNode* current = hashtable->array[i];
        while (current != NULL) {
            HashNode* temp = current;
            current = current->next;
            free(temp->key);//释放节点的空间
            free(temp);//释放节点的指针成员空间
        }
    }
    free(hashtable);//释放哈希表的空间
}


目录
相关文章
|
11月前
|
存储 缓存 数据库
哈希表
【10月更文挑战第24天】哈希表是一种非常实用的数据结构,它在各种计算机应用中发挥着重要作用。通过深入了解哈希表的原理、实现和应用,我们可以更好地利用它来解决实际问题。
|
JSON 安全 算法
API接口安全设计
API接口安全设计
9216 0
API接口安全设计
|
缓存 关系型数据库 MySQL
面试题目总结
面试题目总结
295 6
|
机器学习/深度学习 人工智能 自然语言处理
基于PAI-QuickStart搭建一站式模型训练服务体验
【8月更文挑战第5天】基于PAI-QuickStart搭建一站式模型训练服务体验
350 0
|
NoSQL 编译器 Linux
CodeBlocks-20.03下载安装及中文教程
CodeBlocks-20.03下载安装及中文教程
3169 5
|
程序员 PHP
PHP快速入门12-异常处理,自定义异常、抛出异常、断言异常等示例
PHP的异常处理机制可以帮助我们在程序运行时遇到错误或异常情况时,及时发出警告并停止程序继续运行。下面是10个例子,分别展示了PHP异常处理的不同用法。
410 0
|
负载均衡 算法 应用服务中间件
解密Nginx负载均衡:实现流量分发与故障转移
解密Nginx负载均衡:实现流量分发与故障转移
318 0
|
存储 安全 Java
这些年背过的面试题——多线程篇
本文是技术人面试系列多线程篇,面试中关于多线程都需要了解哪些基础?一文带你详细了解,欢迎收藏!
|
XML 前端开发 数据安全/隐私保护
Shiro - RememberMe记住我功能实现
Shiro - RememberMe记住我功能实现
266 1
|
数据采集 监控 供应链
MES系统软件体系架构及应用
MES系统是数字化车间的核心。MES通过数字化生产过程控制,借助自动化和智能化技术手段,实现车间制造控制智能化、生产过程透明化、制造装备数控化和生产信息集成化。生产管理MES系统主要包括车间管理系统、质量管理系统、资源管理系统及数据采集和分析系统等,由技术平台层、网络层以及设备层实现。
2282 1