一、哈希表的概念及作用
在一般的线性表或者树中,我们所储存的值写它的存储位置的关系是随机的。因此,在查找过程中,需要一系列的与关键字的比较。线性表查找的时间复杂度为O(n)而平衡二叉树的查找的时间复杂度为O(log(n)),时间复杂度较大,而哈希表主要思想是通过将值与其存储位置相关联,来实现快速的随机存储。
二、uthash简介
uthash是C语言的hash表实现,他以宏定义的方式实现哈希表,不仅加快了运行的速度,而且与关键类型无关的优点。
包含头文件:uthash.h
uthash支持的操作有:
- 增删查
- 计数
- 排序
- 选择/查找
- 迭代
三、uthash基本用法
第一步:包含头文件
#include "uthash.h"
第二步:自定义数据结构
每个结构体代表一个键值对,并且,每个结构中要有一个UT_hash_handle
成员。
struct my_struct {
int id; //key
char name[10];
UT_hash_handle hh; /* makes this structure hashable */
};
第三步:定义hash表指针
定义自定义数据结构的指针,并初始化为NULL
struct my_struct *users = NULL; /* important! initialize to NULL */
第四步:进行一般操作
- 增加
 使用第三步定义的users指针添加:
HASH_ADD_INT( users, id, s );//(hash表指针,,新增的结构体成员)
int add_user(int user_id, char *name) {
struct my_struct *s;
HASH_FIND_INT(users,&user_id,s);//重复性检查
if(s==NULL){
s = malloc(sizeof(struct my_struct));
s->id = user_id;
strcpy(s->name, name);
HASH_ADD_INT( users, id, s ); /* id: name of key field */
}
}
- HASH_ADD_INT表示添加的键值为int类型
- HASH_ADD_STR表示添加的键值为字符串类型
- HASH_ADD_PTR表示添加的键值为指针类型
- HASH_ADD表示添加的键值可以是任意类型
- HASH_FIND(hh, users, &user_id, sizeof(user_id), tmp); //tmp用于if(tmp!=NULL{}); user_id为键值
- 查找
struct my_struct *find_user(int user_id) {
struct my_struct *s;
HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
return s;
}
- 删除
void delete_user(struct my_struct *user) {
HASH_DEL( users, user); /* user: pointer to delete */
free(user); /* optional; it’s up to you! */
}
循环删除:
void delete_all() {
struct my_struct *current_user, *tmp;
HASH_ITER(hh, users, current_user, tmp) {
HASH_DEL(users, current_user);
free(current_user);
}
}
- 计数
unsigned int num_users = HASH_COUNT(users);
- 迭代
void print_users() {
struct my_struct *s;
for(s=users; s != NULL; s=s->hh.next) {
printf("user id %d: name %s/n", s->id, s->name
}
}
- 排序
int name_sort(struct my_struct *a, struct my_struct *b) {
return strcmp(a->name,b->name);
}
int id_sort(struct my_struct *a, struct my_struct *b) {
return (a->id - b->id);
}
//按照值排序
void sort_by_name() {
HASH_SORT(users, name_sort); //将name_sort函数传入
}
//按照键排序
void sort_by_id() {
HASH_SORT(users, id_sort);
}
- 替换
HASH_REPLACE宏等效于HASH_ADD宏,HASH_REPLACE会尝试查找和删除项目外。如果找到并删除了一个项目,它还将返回该项目的指针作为输出参数。
void replace_user(my_struct *head, my_struct *newNode) {
HashNode *oldNode = find_user(*head, newNode->id);
if (oldNode)//如果找到id
HASH_REPLACE_INT(*head, id, newNode, oldNode);
}
- 删除哈希表所有元素
如果只想删除所有项目,但不释放它们或进行每个元素的清理,则可以通过一次操作更有效地做到这一点:
HASH_CLEAR(hh, users);
之后,列表头(此处为users)将设置为NULL。