在计算机科学中,哈希表是一种非常高效的数据结构,用于实现键值对的快速插入、查找和删除。然而,当多个键映射到同一个哈希地址时,就会发生冲突。为了解决这个问题,有多种方法,其中开放地址法是C语言中最常用的一种。
本文将带你从零开始,深入浅出地理解C语言哈希表中的开放地址法,并提供完整的可运行代码示例,即使你是编程小白,也能轻松掌握!
开放地址法(Open Addressing)是一种处理哈希冲突的策略。当发生冲突时,它不会使用链表等额外结构,而是在哈希表内部寻找下一个“空闲”的位置来存放冲突的元素。
常见的探测方式有:
下面我们用C语言实现一个简单的哈希表,使用线性探测作为开放地址法的策略。
#include <stdio.h>#include <stdlib.h>#define TABLE_SIZE 10#define EMPTY -1 // 表示该位置为空#define DELETED -2 // 表示该位置曾被删除typedef struct { int key; int value;} HashItem;// 哈希表结构HashItem hashTable[TABLE_SIZE];// 初始化哈希表void initHashTable() { for (int i = 0; i < TABLE_SIZE; i++) { hashTable[i].key = EMPTY; }}// 简单的哈希函数int hashFunction(int key) { return key % TABLE_SIZE;}// 插入键值对void insert(int key, int value) { int index = hashFunction(key); int originalIndex = index; // 线性探测寻找空位 while (hashTable[index].key != EMPTY && hashTable[index].key != DELETED && hashTable[index].key != key) { index = (index + 1) % TABLE_SIZE; // 如果回到起点,说明表已满 if (index == originalIndex) { printf("哈希表已满,无法插入!\n"); return; } } hashTable[index].key = key; hashTable[index].value = value;}// 查找键对应的值int search(int key) { int index = hashFunction(key); int originalIndex = index; while (hashTable[index].key != EMPTY) { if (hashTable[index].key == key) { return hashTable[index].value; } index = (index + 1) % TABLE_SIZE; if (index == originalIndex) break; // 已遍历完整个表 } return -1; // 未找到}// 删除键值对(懒删除)void deleteKey(int key) { int index = hashFunction(key); int originalIndex = index; while (hashTable[index].key != EMPTY) { if (hashTable[index].key == key) { hashTable[index].key = DELETED; hashTable[index].value = 0; return; } index = (index + 1) % TABLE_SIZE; if (index == originalIndex) break; } printf("未找到要删除的键:%d\n", key);}// 打印哈希表void printHashTable() { printf("当前哈希表状态:\n"); for (int i = 0; i < TABLE_SIZE; i++) { if (hashTable[i].key == EMPTY) { printf("%d: [空]\n", i); } else if (hashTable[i].key == DELETED) { printf("%d: [已删除]\n", i); } else { printf("%d: (%d, %d)\n", i, hashTable[i].key, hashTable[i].value); } } printf("\n");}// 主函数测试int main() { initHashTable(); insert(5, 50); insert(15, 150); // 与5冲突,线性探测到下一位 insert(25, 250); // 再次冲突 insert(7, 70); printHashTable(); printf("查找 key=15 的值: %d\n", search(15)); printf("查找 key=99 的值: %d\n", search(99)); deleteKey(15); printHashTable(); return 0;} 1. EMPTY 和 DELETED 标记:我们使用 -1 表示空槽,-2 表示已被删除的槽。这是为了确保查找操作能正确跳过已删除项但继续探测。
2. 循环探测:使用 (index + 1) % TABLE_SIZE 实现环形探测,避免越界。
3. 表满判断:如果探测一圈又回到起点,说明表已满,无法插入新元素。
优点:
缺点:
通过本教程,你已经掌握了C语言哈希表中开放地址法的基本原理和实现方式。这种C语言冲突解决策略非常适合内存受限或对缓存性能要求高的场景。
记住,良好的哈希表实现需要选择合适的哈希函数、表大小(建议质数)和负载因子控制。希望你能动手尝试修改代码,比如实现二次探测或双重哈希,进一步加深理解!
本文由主机测评网于2025-12-03发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025122491.html