数据结构与算法: 哈希表 C语言描述

193 阅读2分钟

1. 目标:实现一个简易哈希表

期望构建一个这样的简易哈希表:

  • 长度为10(实际长度应该用质数,这样更不容易碰撞,demo就随意了)
  • 使用time33散列函数
  • key使用16位字符串
  • data使用int
  • 用单向链表处理哈希碰撞
  • 暂不支持扩容重哈希

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散列函数

这里因为要放在长度为HASHSIZEHashTable里,故而对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!