引入所需的头文件
一般高级语言都会有封装好的hash存储结构,使用c语言的时候同样也可以实现hash,我们自己实现的话逻辑会非常复杂,并且可能会出错,这里我们需要利用一个第三方开源的头文件uthash.h
来实现,大家可以在github或者码云上面找到这个文件。
另外,在官网也有它的用法介绍,链接附上;
下面我们利用这个头文件来实现一个hash结构,实现添加元素、删除元素、统计元素个数、遍历元素等功能。
hash的实现
官方文档说我们需要实现这样的一个结构体,以便我们实现hash表这个结构。UT_hash_handle hh;
是我们把这个结构体变成hash表所必须的一个字段,我们只需要在结构体中定义即可。
#include <stdio.h> /* gets */
#include <stdlib.h> /* atoi, malloc */
#include <string.h> /* strcpy */
#include "uthash.h"
struct MyStruct{
int key;
char value[10];
UT_hash_handle hh;
};
首先我们需要声明一个hash,
struct MyStruct *g_user = NULL; /* important! initialize to NULL */
添加元素
void addUser(int ikey,char * ivalue){
struct MyStruct *s;
HASH_FIND_INT(g_user,&ikey,s);
if(s==NULL){
s=(struct MyStruct *)malloc(sizeof(struct MyStruct));
s->key=ikey;
HASH_ADD_INT(g_user,key,s);
}
strcpy(s->value,ivalue);
}
根据key获取元素
struct MyStruct * getUser(int key){
struct MyStruct *s;
HASH_FIND_INT(g_user,&key,s);
return s;
}
根据key删除元素
void deleteUser(int key){
struct MyStruct *s = NULL;
HASH_FIND_INT(g_user,&key,s);
if(s!=NULL){
HASH_DEL(g_user,s);
free(s);
}
}
获取元素的总个数
int getNum(){
return HASH_COUNT(g_user);
}
删除所有的元素
void delAll(){
struct MyStruct *current,*temp;
HASH_ITER(hh,g_user,current,temp){
HASH_DEL(g_user,current);
free(current);
}
}
判断是否包含某个键值为key的元素
int containUser(int key){
struct MyStruct *s = NULL;
HASH_FIND_INT(g_user,&key,s);
return s!=NULL;
}
遍历输出所有的元素
void printUsers() {
struct MyStruct *s;
for(s=g_user; s != NULL; s=(struct MyStruct*)(s->hh.next)) {
printf("user id %d: name %s\n", s->key, s->value);
}
}
基础的演示
int main(int argc, char *argv[]) {
char in[10];
int id=1, running=1,i;
struct MyStruct *s;
unsigned num_users;
while (running) {
printf(" 1. add user\n");
printf(" 2. contain user?\n");
printf(" 3. find user\n");
printf(" 4. delete user\n");
printf(" 5. delete all users\n");
printf(" 6. print users\n");
printf(" 7. count users\n");
printf(" 8. quit\n");
gets(in);
switch(atoi(in)) {
case 1:
printf("name?\n");
addUser(id++, gets(in));
break;
case 2:
printf("id?\n");
i=atoi(gets(in));
i = containUser(i);
if(i)printf("Contain !\n");
else printf("NO contain !\n");
break;
case 3:
printf("id?\n");
s = getUser(atoi(gets(in)));
printf("user: %s\n", s ? s->value : "unknown");
break;
case 4:
printf("id?\n");
i = atoi(gets(in));
deleteUser(i);
break;
case 5:
delAll();
break;
case 6:
printUsers();
break;
case 7:
num_users=HASH_COUNT(g_user);
printf("there are %u users\n", num_users);
break;
case 8:
running=0;
break;
}
}
// delete_all(); /* free any structures */
return 0;
}
另外,对于hash的实现,键值可以是不同的类型,可以是指针,也可以是另一个结构体类型,等等。官网介绍非常详细,可以直接参阅。