前一节介绍是最简单的冲突解决方法-链接法。开放寻址与链接法不同,所有元素都放在散列表内。
在这种方法中,散列表可能会被填满。开放寻址不需要指针,只需要计算出要存取的各个槽。
由于不用存储指针而节省的空间可以提供更多的槽。
有三种技术常用来计算开放寻址法中的探查序列:线性探查、二次探查和双重探查。
下面的实现中,三种方法的差别只在计算探查序列的那一行代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 20
typedef struct _Entry {
char *key;
char *val;
} Entry;
// 指针数组
Entry *hashmap[SIZE];
// Same as hashcode when String put to HashMap
unsigned hashcode(char *key)
{
// Ensure >> is logical shift
unsigned h = 0;
// String.hashcode()
do h = 31 * h + *key++;
while (*key != '\0');
// HashMap.hash()
h ^= (h >> 20) ^ (h >> 12);
return h ^ (h >> 7) ^ (h >> 4);
}
Entry * hashmap_search(char *key)
{
unsigned h = hashcode(key) % SIZE;
unsigned h2 = h;
Entry *entry = hashmap[h];
while (entry != NULL) {
if (strcmp(entry->key, key) == 0) {
return entry;
}
// 线性探查。不同探查方法差别只在这一行。
h = (h + 1) % SIZE;
entry = hashmap[h];
if (h == h2)
break;
}
return NULL;
}
char * hashmap_insert(char *key, char *val)
{
unsigned h = hashcode(key) % SIZE;
printf("Insert %s - %s to bucket %d\n", key, val, h);
// Find duplicate key, replace it then return old value
unsigned h2 = h;
Entry *entry = hashmap[h];
while (entry != NULL) {
if (strcmp(entry->key, key) == 0) {
char *oldVal = entry->val;
entry->val = val;
return oldVal;
}
// Linear search
h = (h + 1) % SIZE;
entry = hashmap[h];
// Check if loop to initial bucket
if (h == h2)
break;
}
// Not found, create new node to save key&val pair
if (entry == NULL) {
entry = malloc(sizeof(Entry));
entry->key = key;
entry->val = val;
hashmap[h] = entry;
}
return val;
}
void hashmap_print()
{
Entry *entry;
int i;
for (i = 0; i < SIZE; i++) {
entry = hashmap[i];
if (entry == NULL)
printf("%d: null\n", i);
else
printf("%d: %s - %s\n", i, entry->key, entry->val);
}
printf("\n");
}
int main(void)
{
// Compare to String.hashcode() in JDK
printf("%d\n", hashcode("helloworld"));
hashmap_insert("aabb", "value1");
hashmap_insert("ccdd", "value2");
hashmap_insert("i'mcdai", "value3");
int i;
for (i = 0; i < 2 * SIZE + 5; i++) {
char *key = calloc(sizeof(char), 10);
char *val = calloc(sizeof(char), 10);
sprintf(key, "%s%d", "aabbcc", i);
sprintf(val, "%s%d", "val ", i);
hashmap_insert(key, val);
}
// Insert duplicate key
printf("%s\n", hashmap_insert("i'mcdai", "dupdup"));
hashmap_print();
printf("%s\n", hashmap_search("i'mcdai")->val);
hashmap_print();
return 1;
}
分享到:
相关推荐
算法导论第四章答案算法导论第四章答案算法导论第四章答案算法导论第四章答案
最近在研习算法导论,发现课后习题的精彩程度甚至不亚于正文,对于算法导论的爱好者而言,这是一份不错的参考资料
算法导论 第二十五章 答案 算法导论 第二十五章 答案 算法导论 第二十五章 答案
算法导论第二十四章答案 算法导论第二十四章答案 算法导论第二十四章答案
算法导论第15章-动态规划的课后习题参考答案,对于算法爱好者而言,是不错的参考资料。
算法导论大作业:股票买卖最佳时期系列问题 南开大学 算法导论源码算法导论大作业:股票买卖最佳时期系列问题 南开大学 算法导论源码算法导论大作业:股票买卖最佳时期系列问题 南开大学 算法导论源码算法导论大作业...
本章问题较多的设计到数论与概率工具,由于对数学工具掌握的不够熟悉,有些习题尚未完成
基本上完整的算法导论第三版课后答案,中文版!
能用代码表示的都用代码表示,不能表示的写出思路,思路都没写的就是我也做不出来
第11章 散列表 第12章 二叉查找树 第13章 红黑树 第14章 数据结构的扩张 第四部分 高级设计和分析技术 导论 第15章 动态规划 第16章 贪心算法 第17章 平摊分析 第五部分 高级数据结构 概述 第18章 B树 第19章 二项堆...
算法导论讲义\算法导论讲义 算法导论讲义\算法导论讲义 算法导论讲义\算法导论讲义 MIT教师的课堂讲义 很有价值
能用代码表示的都用代码表示,不能表示的写出思路,思路都没写的就是我也做不出来
31~35章
计算机算法导论计算机算法导论计算机算法导论计算机算法导论计算机算法导论
第十一章 散列表(Hash Tables) 第十二章 二叉查找树(Binary Search Trees) 第十三章 红-黑树(Red-Black Trees) 第十四章 扩充的数据结构(Augmenting Data Structures) 第四部分(Part IV) ...
能用代码表示的都用代码表示,不能表示的写出思路,思路都没写的就是我也做不出来
算法导论第二版课后答案中文完全版是算法导论的课后答案有 完整的解题过程 对于学好算法有很大帮助
算法导论
能用代码表示的都用代码表示,不能表示的写出思路,思路都没写的就是我也做不出来
MIT 算法导论part3MIT 算法导论part3MIT 算法导论part3MIT 算法导论part3MIT 算法导论part3MIT 算法导论part3