ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

uthash详解

2022-07-24 00:33:23  阅读:283  来源: 互联网

标签:node head HASH name 详解 key uthash ptr


库函数

//新增元素
HASH_ADD_INT(head, keyfield_name, item_ptr);
HASH_ADD_STR(head, keyfield_name, item_ptr);
HASH_ADD_PTR(head, keyfield_name, item_ptr);
//查找元素
HASH_FIND_INT(head, key_ptr, item_ptr);
HASH_FIND_STR(head, key_ptr, item_ptr);
HASH_FIND_PTR(head, key_ptr, item_ptr);
//删除元素
HASH_DEL(head, item_ptr);
//返回长度
HASH_COUNT(head);
//释放堆区内存
HASH_CLEAR(hh_name, head);
//排序,cmp_func书写规则和qsort一样。
HASH_SORT(head, cmp_func);

参数介绍:
head: 哈希表变量,是一个结构体指针
keyfield_name: 结构体内键的定义名称
item_ptr: 新增节点的指针
key_ptr: 键变量的指针
hh_name: UT_hash_handle变量的定义名称

正文

上面列出了常用的库函数(都是便利版本,如果想要更高的灵活性请参考原文链接uthash
正常来说,上面这些就足够刷题使用了。

下面是uthash的使用步骤:

  1. 需要自定义一个结构体
typedef struct
{
	int key;
	char name[20];
	uint8_t age;
	UT_hash_handle hh;
} HashMap;
static HashMap *head = NULL;

这里必须的只有两个,一个是UT_hash_handle hh;,映射就是通过这个宏实现的,变量名称最好定义为hh,否则上面介绍的便利版本宏函数全部用不了(便利版本内部默认使用hh导致)。当然定义成别的名称也不是不行,函数就得用通用版本,参数更多也更难记,总不能既要有要还要吧~
另一个就是key变量,便利版本支持三种类型:int,char *,void *,查找会用到该字段。
最后声明一个全局变量head,他就是hash表的入口,初始化必须是NULL。所有函数都会用到他。

  1. 定义几个操作函数
HashMap *Find(const int key)
{
	HashMap *node = NULL;
	HASH_FIND_INT(head, &key, node);	//如果是int,要取地址,str或ptr不需要
	return node;
}

void Add(const int key, const char *name, const uint8_t age)
{
	HashMap *node = Find(key);
	if (!node)
	{
		node = (HashMap *)malloc(sizeof(HashMap));
		node->key = key;
		node->age = age;
		strcpy_s(node->name, sizeof(node->name), name);
		HASH_ADD_INT(head, key, node);	//注意,这里key其实是结构体主键的定义名称,而不是变量。
	}
}

void Delete(const int key)
{
	HashMap *node = Find(key);
	if (node)
	{
		HASH_DEL(head, node);
		free(node);		//最好free一下,毕竟节点删掉了。
	}
}

为什么要定义这些呢?
很简单,为了代码可读,为了少写点代码字数(C大概是所有现代语言里最繁琐的一种了),具体看下文主函数的内容就知道了。
接下来简单说下。

  • Find是查找hash表,找到了就返回结构体指针,找不到返回NULL;
  • Add是给hash表新增元素,必须包含结构体所有字段;
  • Delete是删除某个元素
  • 如果有别的需求,比如不用key来找,用name来找,那么修改下Find函数即可(但是性能肯定会下降很多,O(1)->O(N));
  • 如果想要修改,查到了直接改就行,很简单所以没封装成函数。
  1. 接下来是主函数
int main()
{
	Add(0, "zhang san", 18);	//这里一条就可以加一个映射关系
	Add(1, "li si", 21);
	Add(2, "wang wu", 31);
	for (int i = 0; i < HASH_COUNT(head); i++)
	{
		printf("name: %s    age: %d\n", Find(i)->name, Find(i)->age);
	}
	HASH_CLEAR(hh, head);	//必须,千万别忘了写
	return 0;
}

打印结果为:

name: zhang san    age: 18
name: li si    age: 21
name: wang wu    age: 31

这里要特别注意,最后必须要调用HASH_CLEAR(hh, head);,否则堆内存未被释放,在线编程会导致内存错误或结果不正确。
到这里,库函数和简单演示都结束了~

后记

这个hash库可以做很多事情,因为他使用自定义结构体做节点,结构体里可以塞各种变量,主键和结构体会产生映射关系。
如果只有主键,那么就是个set;
如果除了主键还有其他结构体元素,那他就是个map;
如果Add函数不查重,那么他就是multi版本的set和map;
默认情况下是无序的,如果sort一下,他就是有序的。
这么看来,它就把C++里的8种set和map都覆盖了呢~

标签:node,head,HASH,name,详解,key,uthash,ptr
来源: https://www.cnblogs.com/mrzono/p/16513591.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有