简单HashTable的实现,编程语言C
相关头文件和预处理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#define HASH_SIZE 10 //定义hashtable的桶的大小
#define list_for_table \ //用于循环遍历hashtable
for(i = 0; i < HASH_SIZE; i++)
typedef unsigned int uint;
相关结构体定义
struct hash_node //定义hashtable的节点
{
char *key; //char*的key
uint value; //无符号整型的值字段
struct hash_node *next;
};
struct hash_table //定义hashtable
{
struct hash_node *bucket; //定义hash桶
int number; //hashtable内的节点数
};
Hash函数采用的是BKDR, 附上参考链接
static uint bkdr_hash(char *p)
{
uint seed, hash;
seed = 131, hash = 0;
while(*p != '\0')
hash = hash * seed + (*p++);
return hash;
}
static uint key_to_index(char *key)
{
uint bdkr_hash, index;
bdkr_hash = bkdr_hash(key);
index = bdkr_hash % (HASH_SIZE - 1);
return index;
}
Hash基本操作
/*
* Descrition: 分配hash节点函数
* @i: 如果分配一个,那么i设置1
*/
static struct hash_node *malloc_node(uint i)
{
return (struct hash_node *)malloc(sizeof(struct hash_node) * i);
}
/*
* Description: 哈希表的初始化
*/
static struct hash_table *hash_init()
{
struct hash_table *t;
t = (struct hash_table *)malloc(sizeof(struct hash_table));
t->bucket = malloc_node(HASH_SIZE);
memset(t->bucket, 0, sizeof(struct hash_node) * HASH_SIZE);
return t;
}
/*
* Description: 哈希表的打印
* @t: 待打印的哈希表的地址
*/
static void hash_display(struct hash_table *t)
{
int i;
struct hash_node *pos;
printf("the num of the element of this table is %d\n", t->number);
list_for_table
{
pos = t->bucket + i;
if(!pos) continue;
pos = pos->next;
printf("Bucket[%d]:\n", i);
while(pos)
{
printf(" key=%-10svalue=%-10d\n", pos->key, pos->value);
pos = pos->next;
}
}
}
/*
* Description: 哈希表的释放
* @t: 待释放的哈希表的地址
*/
static void hash_free(struct hash_table *t)
{
int i;
struct hash_node *pos, *tmp;
list_for_table
{
pos = t->bucket + i;
if(!pos) continue;
pos = pos->next;
while(pos)
{
tmp = pos->next;
pos->key = NULL;
free(pos);
pos = tmp;
}
}
free(t);
}
/*
* Description: 哈希表的插入函数
* @key: char *, key字段
* @value: unsigned int, 值字段
* @t: struct hash_table *, 待插入的哈希表的地址
*/
static uint insert_table(char *key, uint value, struct hash_table *t)
{
uint index;
struct hash_node *pos, *tmp;
index = key_to_index(key);
//printf("%s, index is %d\n", __FUNCTION__, index);
tmp = pos = t->bucket + index;
pos = pos->next; // bucket do not store data
while(pos)
{
if(strcmp(key, pos->key) == 0)
{
pos->value = value;
return 0;
}
tmp = pos;
pos = pos->next;
}
pos = malloc_node(1);
tmp->next = pos;
pos->value = value;
pos->key = key;
pos->next = NULL;
t->number++;
return 0;
}
/*
* Description: 哈希表的查找函数
* @key: char *, key字段
* @t: struct hash_table *, 待查找的哈希表的地址
*/
static struct hash_node *search_table(char *key, struct hash_table *t)
{
uint index;
struct hash_node *pos;
if(NULL == t) return NULL;
index = key_to_index(key);
//printf("%s, index is %d\n", __FUNCTION__, index);
pos = t->bucket + index;
pos = pos->next; //the bucket do not store data
while(pos)
{
if(strcmp(key, pos->key) == 0)
return pos;
pos = pos->next;
}
return NULL;
}
/*
* Description: 哈希表的删除节点函数
* @key: char *, key字段
* @t: struct hash_table *, 待删除节点的哈希表的地址
*/
static uint delete_table(char *key, struct hash_table *t)
{
uint index;
struct hash_node *pos, *tmp;
index = key_to_index(key);
//printf("%s, index is %d\n", __FUNCTION__, index);
if(NULL == t) return 1; //返回1, 哈希表为空
tmp = pos = t->bucket + index;
pos = pos->next; //bucket do not store data
while(pos)
{
if(strcmp(key, pos->key) == 0)
{
tmp->next = pos->next;
pos->key = NULL;
free(pos);
t->number--;
return 0; //返回0, 删除节点成功
}
tmp = pos;
pos = pos->next;
}
return -1; //返回-1, 哈希表内无相匹配的key
}
测试代码, 将上述代码写进hash.h, 然后新建disp.c
#include <stdio.h>
#include "hash.h"
struct hash_table *t = NULL;
static void disp_menu()
{
printf("----------------------My_Hash----------------------\n");
printf("1. Insert Into Hash Table \n");
printf("2. Search From Hash Table \n");
printf("3. Delete From Hash Table \n");
printf("4. Display Hash Table \n");
printf("5. Quit \n");
printf("Please Input the Number to Select the Function(1-5):\n ");
printf("----------------------My_Hash----------------------\n");
printf("Your Input is:");
}
static void insert_menu()
{
char *key;
uint value, ret;
key = (char *)malloc(sizeof(char) * 10);
printf("1. Insert Into Hash Table \n");
printf(" Please Input the Key:");
scanf("%s", key);
//getchar();
printf(" Please Input the Value:");
scanf("%d", &value);
ret = insert_table(key, value, t);
if(!ret)
printf(" Insert Successfully!\n");
}
static void search_menu()
{
char *key;
struct hash_node *node;
key = (char *)malloc(sizeof(char) * 10);
printf("1. Search From Hash Table \n");
printf(" Please Input the Key:");
scanf("%s", key);
node = search_table(key, t);
if(node == NULL)
printf(" We Do Not Search the Matchable Value!\n");
else
printf(" key=%-10svalue=%-10d\n", node->key, node->value);
}
static void delete_menu()
{
char *key;
uint ret;
key = (char *)malloc(sizeof(char) * 10);
printf("1. Delete From Hash Table \n");
printf(" Please Input the Key:");
scanf("%s", key);
ret = delete_table(key, t);
if(ret == 1)
printf(" Table is NULL!\n");
else if(ret = -1)
printf(" We Do Not Search the Matchable Value!\n");
else
printf(" Delete Successfully!\n");
}
static void display_menu()
{
printf("1. Display Hash Table \n");
hash_display(t);
}
static void disp_end()
{
printf(" Continue Or Quit(y/n): ");
}
static void match_condition(int x)
{
switch (x)
{
case 1:
insert_menu();
break;
case 2:
search_menu();
break;
case 3:
delete_menu();
break;
case 4:
display_menu();
break;
case 5:
break;
default:
break;
}
}
int main()
{
int x;
char ch = 'y';
t = hash_init();
disp_menu();
scanf("%d", &x);
while(x != 5)
{
match_condition(x);
disp_end();
getchar();
ch = getchar();
if(ch == 'n')
break;
else if(ch == 'y')
{
disp_menu();
scanf("%d", &x);
}
}
printf("----------------------Bye,Bye----------------------\n");
return 0;
}
编译运行
# 实验环境
# OS: Ubuntu18.04
# gcc version: 7.3.0-27
cd $workspace # workspace是你的代码目录
gcc disp.c -o disp
./disp
感想
这个hash的实现是参考的网上的一些资料, 随后附上
哈希表的实现没啥问题, 主要是测试里面C的一些堆栈溢出, 各种segment fault
万幸的是都解决了,
最后附上参考帖子
https://blog.csdn.net/yyyljw/article/details/80903391
https://blog.csdn.net/hu694028833/article/details/79114877