1. 目标:实现一个简易哈希表
期望构建一个这样的简易哈希表:
- √ 长度为10(实际长度应该有质数,这样更不容易碰撞)
- √ 使用time33散列函数
- √ key使用16位字符串
- √ data使用int
- √ 用单向链表处理哈希碰撞
- X 暂不支持扩容重哈希
2. 代码实现
2.1 哈希节点结构体
#define HASHSIZE 10
typedef struct HashNode {
char key[16];
int data;//数据域
struct HashNode *next;//指针域,哈希碰撞时候的后继结点
} HashNode;
static HashNode *HashTable[HASHSIZE];
2.2 time33
散列函数
这里因为要放在长度为HASHSIZE
的HashTable
里,故而对HASHSIZE
取余
typedef struct HashNode {
char key[16];
int data;//数据域
struct HashNode *next;//指针域,哈希碰撞时候的后继结点
} HashNode;
static HashNode *HashTable[HASHSIZE];
2.3 set
函数
- 考虑该槽为
NULL
时直接插入- 考虑该槽不为空时,则遍历链表寻找目标
key
, 找得到就更新, 找不到就尾插新节点
void *set(char *key, int data)
{
struct HashNode *node;
unsigned int hash_key = time33(key);
printf("set key:%s val:%d hash:%d\n", key, data, hash_key);
struct HashNode *new_node;
new_node = (struct HashNode *)malloc(sizeof(struct HashNode));
strcpy(new_node->key, key);
new_node->data = data;
new_node->next = NULL;
node = HashTable[hash_key];
//先看在不在
if (NULL == node)
{
HashTable[hash_key] = new_node;
return NULL;
}else if(strcmp(node->key, key) == 0){
printf("update key:%s %d => %d \n",key,node->data, data);
//update
node->data = data;
free(new_node);
}else{
//碰撞
while(node->next != NULL){
node = node->next;
if(strcmp(node->key, key) == 0){
//update
node->data = data;
printf("update key:%s %d => %d \n",key,node->data, data);
free(new_node);
}
}
node->next = new_node;
}
}
2.4 get
函数
- 考虑该槽为
NULL
时返回NULL
- 考虑该槽不为空时,则遍历链表寻找目标
key
, 找得到就返回该节点, 找不到返回NULL
HashNode *get(char *key)
{
unsigned int hash_key = time33(key);
struct HashNode *node;
node = HashTable[hash_key];
while(NULL != node){
if (strcmp(key, node->key) == 0)
{
printf("get %s :%d \n", key, node->data);
return node;
}
node = node->next;
}
return NULL;
}
2.5 遍历哈希getAll
函数 用于验证代码
void getAll(){
struct HashNode *node;
for (int i = 0; i < HASHSIZE; ++i)
{
if (HashTable[i] != NULL)
{
node = HashTable[i];
while(node != NULL){
printf("%d %s %d \n", i,node->key,node->data);
node = node->next;
}
}
}
}
3 测试代码
int main(int argc, char const *argv[])
{
set("zhangsan", 100);
set("zhangsan", 200);//update
set("lisi", 200);
set("wangwu", 300);
set("maliu", 400);
set("qianer", 500);
set("zhaojiu", 600);
set("sunzi",700);
set("wangwu", 3000);//update
getAll();
return 0;
}
Res:
terence@k8s-master:/mydata/c$ gcc hashTable.c
terence@k8s-master:/mydata/c$ ./a.out
set key:zhangsan val:100 hash:1
set key:zhangsan val:200 hash:1
update key:zhangsan 100 => 200
set key:lisi val:200 hash:6
set key:wangwu val:300 hash:0
set key:maliu val:400 hash:1
set key:qianer val:500 hash:5
set key:zhaojiu val:600 hash:7
set key:sunzi val:700 hash:4
set key:wangwu val:3000 hash:0
update key:wangwu 300 => 3000
0 wangwu 3000
1 zhangsan 200
1 maliu 400
4 sunzi 700
5 qianer 500
6 lisi 200
7 zhaojiu 600
Done!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。