开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情
简介
在一个项目开发过程中,哈希表在大量数据的处理过程里不可避免的一种数据结构。如果自己构建,算法的设计是个比较复杂的任务。算法好的情况下,可以做到常数插入,常数读取的效率。故不必重复造轮子,有轮子拿来直接用,有兴趣可以拆轮子自己研究一下。 下载地址 :github.com/troydhanson… 文档:troydhanson.github.io/uthash/
全部依赖的文件只有一个头文件,结构上简单粗暴。 可以看一下这个开源项目的结构
src文件夹中就是我们需要依赖的头文件。
头文件使用宏编写,所以编译阶段会直接内链到我们的代码中,效率没有影响。
doc文件夹中包含使用文档。
tests文件夹中包含测试代码。
接口类型
哈希结构体定义
#include "uthash.h"
struct my_struct {
int id; /* key */
char name[10];
UT_hash_handle hh; /* makes this structure hashable */
};
添加
UTHASH_VERSION:版本号
HASH_ADD_INT:添加新节点,键值是整数
HASH_ADD_STR:添加新节点,键值是字符串
HASH_ADD:添加新节点,不关心类型
查找
HASH_FIND_INT: 查找指定的节点,键值是整数
HASH_FIND_STR: 查找指定的节点,键值是字符串
HASH_FIND_PTR: 查找指定的节点,键值是指针
HASH_FIND: 通用的查找指定的节点
删除
HASH_DEL:从哈希表中删除一个指定的节点
HASH_CLEAR:清空表,最好不用,他不会释放由应用深情的资源
遍历
HASH_SORT:安全的遍历所有的哈希节点
计数
HASH_COUNT
接口使用
添加一个节点,键值是整数型
struct my_struct *users = NULL; //初始化为NULL
int ZAddHash(int KeyId,char* Val)
{
struct my_struct *s;
HASH_FIND_INT(users, &KeyId, s); /* id already in the hash? */
if(s == NULL) return 1;
s = malloc(sizeof *s);
s->id = KeyId;
strcpy(s->name, Val);
HASH_ADD_INT(users, id, s); //这个id是结构体中的id,需一样的名字
return 0;
}
每一个节点都是应用申请的空间,后续需自己删释放
键值应为都是唯一的,不可重复 ,故先检查是否存在该键值。
查找节点
struct my_struct *find_user(int KeyId) {
struct my_struct *s;
HASH_FIND_INT(users, &KeyId, s);
return s;
}
此处也可以使用通用的查找接口:HASH_FIND。
如果失败返回NULL
成功,则返回找到的节点地址
删除节点
int delete_user(int KeyId) {
struct my_struct *user
HASH_FIND_INT(users, &KeyId, user);
if(user == NULL) return 1;
HASH_DEL(users, user); /* user: pointer to deletee */
free(user); /* optional; it's up to you! */
return 0;
}
按照键值,先查找,找到后删除节点,并释放资源
成功返回0
失败返回1,指找不到节点
清空hash表
#typedef void (*func)(int a,void*b)
int clearHash(func Ops)
{
struct my_struct *current_user, *tmp;
HASH_ITER(hh, users, current_user, tmp) {
Ops(1,NULL)
HASH_DEL(users, current_user); /* delete; users advances to next */
free(current_user); /* optional- if you want to free */
}
users = NULL
return 0;
}
定义一个函数指针,在清空表的时候,顺便可以执行一下我们想做的操作
代码
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<uthash.h>
struct my_struct {
int id;
char name[10];
UT_hash_handle hh;
};
struct my_struct *users = NULL; //初始化为NULL
int ZAddHash(int KeyId,char* Val)
{
struct my_struct *s;
HASH_FIND_INT(users, &KeyId, s); /* id already in the hash? */
if(s == NULL) return 1;
s = malloc(sizeof *s);
s->id = KeyId;
strcpy(s->name, Val);
HASH_ADD_INT(users, id, s); //这个id是结构体中的id,需一样的名字
return 0;
}
struct my_struct *find_user(int KeyId) {
struct my_struct *s;
HASH_FIND_INT(users, &KeyId, s);
return s;
}
int delete_user(int KeyId) {
struct my_struct *user
HASH_FIND_INT(users, &KeyId, user);
if(user == NULL) return 1;
HASH_DEL(users, user); /* user: pointer to deletee */
free(user); /* optional; it's up to you! */
return 0;
}
#typedef void (*func)(int a,void*b)
int clearHash(func Ops)
{
struct my_struct *current_user, *tmp;
HASH_ITER(hh, users, current_user, tmp) {
if(Ops)Ops(1,current_user)
HASH_DEL(users, current_user); /* delete; users advances to next */
free(current_user); /* optional- if you want to free */
}
users = NULL
return 0;
}
void PrintfNode(int a,void * ptr)
{
struct my_struct *user = (struct my_struct *)ptr;
printf(" name[%s]\n",user->name);
}
int main(int argc, char** argv)
{
char in[10];
int id=1,
struct my_struct *s;
for(int i = 0;i < 20;i++){
ZAddHash(i,"this is test!!");
}
clearHash(PrintfNode);
return 0;
}
实现的结构并没有全部调用,实现了对添加节点和清空表的测试。