由于 C 语言本身不存在哈希,我们可以调用开源的第三方头文件:uthash.h。使用 uthash 添加,查找和删除通常是常数时间的操作,此哈希的目标是简约高效。它会自动内联,因为它是作为宏实现的。 uthash 还包括三个额外的头文件,主要提供链表,动态数组和字符串。utlist.h 为提供了链接列表宏。utarray.h 使用宏实现动态数组。utstring.h 实现基本的动态字符串。
使用
定义结构体
1
2
3
4
5
6
7
8
#include"uthash.h"structmy_struct{intid;/* key */charname[10];UT_hash_handlehh;/* makes this structure hashable */};/*声明哈希为NULL指针*/structmy_struct*users=NULL;/* important! initialize to NULL */
这里我们将 id 作为一个索引值,也就是键值,将 name 作为 value。一定要包含UT_hash_handle hh; hh 不需要初始化。它可以命名为任何名称,但是我们一般都命名为 hh。
添加
1
2
3
4
5
6
7
8
9
10
11
12
voidadd_user(intuser_id,char*name){structmy_struct*s;/*重复性检查,当把两个相同key值的结构体添加到哈希表中时会报错*/HASH_FIND_INT(users,&user_id,s);/* id already in the hash? *//*只有在哈希中不存在ID的情况下,我们才创建该项目并将其添加。否则,我们只修改已经存在的结构。*/if(s==NULL){s=(structmy_struct*)malloc(sizeof*s);s->id=user_id;HASH_ADD_INT(users,id,s);/* id: name of key field */}strcpy(s->name,name);}
voiddelete_all(){structmy_struct*current_user,*tmp;HASH_ITER(hh,users,current_user,tmp){HASH_DEL(users,current_user);/* delete; users advances to next */free(current_user);/* optional- if you want to free */}}
删除哈希表所有元素
1
HASH_CLEAR(hh,users);
之后,列表头(此处为users)将设置为NULL
哈希表元素个数:
1
2
3
unsignedintnum_users;num_users=HASH_COUNT(users);printf("there are %u users\n",num_users);
当 users 为 NULL 时,HASH_COUNT 会返回 0.
遍历哈希表中的所有项目
1
2
3
4
5
6
7
voidprint_users(){structmy_struct*s;for(s=users;s!=NULL;s=s->hh.next){printf("user id %d: name %s\n",s->id,s->name);}}
#include<string.h> /* strcpy */#include<stdlib.h> /* malloc */#include<stdio.h> /* printf */#include"uthash.h"structmy_struct{charname[10];/* key (string is WITHIN the structure) */intid;UT_hash_handlehh;/* makes this structure hashable */};intmain(intargc,char*argv[]){constchar*names[]={"joe","bob","betty",NULL};structmy_struct*s,*tmp,*users=NULL;for(inti=0;names[i];++i){s=(structmy_struct*)malloc(sizeof*s);strcpy(s->name,names[i]);s->id=i;HASH_ADD_STR(users,name,s);}HASH_FIND_STR(users,"betty",s);if(s)printf("betty's id is %d\n",s->id);/* free the hash table contents */HASH_ITER(hh,users,s,tmp){HASH_DEL(users,s);free(s);}return0;}