1、uthash概述
- uthash是一个用c语言编写的开源库,使用宏实现了哈希表的增删改查等功能
- gitthub仓库地址:https://github.com/troydhanson/uthash
- 官方文档:http://troydhanson.github.io/uthash/userguide.html
2、uthash使用
- Linux下的安装
将下载下来的怎个目录拷贝到/usr/local/include下面
- 初始化
uthash需要用户定义自己的数据结构,一个包含UT_hash_handle hh的结构体
还需要定义键和值(可选),这里将id作为key, name作为value
struct my_struct {
int id; /* key */
char name[10];
UT_hash_handle hh; /* makes this structure hashable */
};
typedef struct my_struct HashNode;
typedef struct my_struct *HashHead;
- 添加
key是int,可以使用 HASH_ADD_INT
key是字符串,可以使用 HASH_ADD_STR
key是指针,可以使用 HASH_ADD_PTR
其它,可以使用 HASH_ADD,上述实际都是调用这个方法,不过简化了参数
void hashTabel_add(HashHead *head, HashNode *users) {
// id是key的属性名字,虽然很奇怪,实际作为宏参数会被替换掉
// 可以看下面源码,intfield会替换换成&((add)->fieldname)
if(!find_user(*head, users->id))
HASH_ADD_INT(*head, id, users);
}
#define HASH_ADD_INT(head,intfield,add) \
HASH_ADD(hh,head,intfield,sizeof(int),add)
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add)
- 替换
与添加差不多,会在添加前,删除key相同的节点,再添加新的节点
如果key是int,可以使用 HASH_REPLACE_INT
void replace_user(HashHead *head, HashNode *newNode) {
HashNode *oldNode = find_user(*head, newNode->id);
if (oldNode)
HASH_REPLACE_INT(*head, id, newNode, oldNode);
}
- 查找
根据key查找节点
如果key是int,可以使用 HASH_FIND_INT
HashNode *find_user(HashHead head, int user_id) {
HashNode *s;
HASH_FIND_INT(head, &user_id, s); /* s: output pointer */
return s;
}
- 删除
void delete_user(HashHead *head,HashNode *user) {
if (user) {
HASH_DEL(*head, user); /* user: pointer to deletee */
free(user); /* optional; it's up to you! */
}
}
- 计数
int count_user(HashHead head) {
return HASH_COUNT(head);
}
- 遍历
void print_user(HashHead head) {
HashNode *s;
printf("size is %d\n", count_user(head));
for (s = head; s != NULL; s = s->hh.next) {
printf("user id %d, name %s\n", s->id, s->name);
}
}
void print_user_iterator(HashHead head) {
HashNode *s, *tmp;
printf("size is %d\n", count_user(head));
HASH_ITER(hh, head, s, tmp) {
printf("user id %d: name %s\n", s->id, s->name);
/* ... it is safe to delete and free s here */
}
}
- 排序
int name_sort(HashNode *a, HashNode *b) {
return strcmp(a->name,b->name);
}
int id_sort(HashNode *a, HashNode *b) {
return (a->id - b->id);
}
void sort_by_name(HashHead *head) {
HASH_SORT(*head, name_sort);
}
void sort_by_id(HashHead *head) {
HASH_SORT(*head, id_sort);
}
3、完整代码
#include <stdio.h>
#include <stdlib.h>
#include "uthash.h"
typedef struct my_struct {
int id; /* we'll use this field as the key */
char name[10];
UT_hash_handle hh; /* makes this structure hashable */
}HashNode;
typedef HashNode* HashHead;
int count_user(HashHead head);
HashNode *find_user(HashHead head, int user_id) {
HashNode *s;
HASH_FIND_INT(head, &user_id, s); /* s: output pointer */
return s;
}
void add_user(HashHead *head, HashNode *users) {
if(!find_user(*head, users->id))
HASH_ADD_INT(*head, id, users);
}
void replace_user(HashHead *head, HashNode *newNode) {
HashNode *oldNode = find_user(*head, newNode->id);
if (oldNode)
HASH_REPLACE_INT(*head, id, newNode, oldNode);
}
void delete_user(HashHead *head,HashNode *user) {
if (user) {
HASH_DEL(*head, user); /* user: pointer to deletee */
free(user); /* optional; it's up to you! */
}
}
void print_user(HashHead head) {
HashNode *s;
printf("size is %d\n", count_user(head));
for (s = head; s != NULL; s = s->hh.next) {
printf("user id %d, name %s\n", s->id, s->name);
}
}
void print_user_iterator(HashHead head) {
HashNode *s, *tmp;
printf("size is %d\n", count_user(head));
HASH_ITER(hh, head, s, tmp) {
printf("user id %d: name %s\n", s->id, s->name);
/* ... it is safe to delete and free s here */
}
}
int count_user(HashHead head) {
return HASH_COUNT(head);
}
int name_sort(HashNode *a, HashNode *b) {
return strcmp(a->name,b->name);
}
int id_sort(HashNode *a, HashNode *b) {
return (a->id - b->id);
}
void sort_by_name(HashHead *head) {
HASH_SORT(*head, name_sort);
}
void sort_by_id(HashHead *head) {
HASH_SORT(*head, id_sort);
}
int main()
{
printf("--------------init---------------\n");
HashHead head = NULL;
printf("--------------add---------------\n");
HashNode *node = malloc(sizeof(HashNode));
node->id = 1;
strcpy(node->name, "tom");
add_user(&head, node);
node = malloc(sizeof(HashNode));
node->id = 2;
strcpy(node->name, "jerry");
add_user(&head, node);
node = malloc(sizeof(HashNode));
node->id = 3;
strcpy(node->name, "jack");
add_user(&head, node);
node = malloc(sizeof(HashNode));
node->id = 0;
strcpy(node->name, "zero");
add_user(&head, node);
print_user(head);
printf("--------------replace---------------\n");
HashNode *newNode = malloc(sizeof(HashNode));
newNode->id = 3;
strcpy(newNode->name, "rose");
replace_user(&head, newNode);
print_user(head);
printf("--------------delete---------------\n");
delete_user(&head, find_user(head, 1));
print_user(head);
printf("--------------sort-by-id---------------\n");
sort_by_id(&head);
print_user(head);
printf("--------------sort-by-name---------------\n");
sort_by_name(&head);
print_user(head);
return 0;
}