网站还在建设中英文,丰顺最新新闻今天,十堰的网站建设,举报非法网站要求做笔录UTHash使用教程
快速入门
想快速入门该模块请访问#xff1a;介绍#xff0c;数据接口#xff0c;示例代码
介绍
Hash #xff1a;散列#xff0c;通过关于键值(key)的函数#xff0c;将数据映射到内存存储中一个位置来访问。这个过程叫做Hash#xff0c;这个映射函…UTHash使用教程
快速入门
想快速入门该模块请访问介绍数据接口示例代码
介绍
Hash 散列通过关于键值(key)的函数将数据映射到内存存储中一个位置来访问。这个过程叫做Hash这个映射函数称做散列函数存放记录的数组称做散列表(Hash Table),又叫哈希表。
C语言中没有专门的hash处理函数因此通常采用第三方编写的库 —— uthash。
uthash是一个使用宏定义处理的C语言哈希表头文件。因此添加uthash只需要 #include “uthash.h” 即可完成高效hash操作。
一般采用hash表时都是希望对某一组数据结构进行高效的增删改查
源码github官网https://github.com/troydhanson/uthash官方教程官网https://troydhanson.github.io/uthash/官方参考示例uthash-master/tests/example.c如果找不到示例代码也可以参考这个博主摘抄的示例也来自官方示例https://blog.csdn.net/fan_h_l/article/details/107241520
数据接口
1. 定义hash结构
假设我们要定义一个{ key : value } 为 { id : data }的哈希表则需要按如下方式进行定义。
typedef struct example_user_t {int id;int data;UT_hash_handle hh;
} example_user_t;2. 接口介绍INT类型的接口宏
uthash的接口都是宏定义因此需要了解每个入参到底是变量还是转义标识符。
首先介绍几个概念便于后续理解
哈希结构 - 代表上文的example_user_t结构体哈希键变量 - 代表上文 int id 中的id哈希键变量的值 - 若上文 int id 8那么8就是这个值哈希值变量 - 代表上文的 int data哈希值变量的值 - 代表上文 data的实际值哈希头 - 通常完成一个哈希表的创建后需要有个哈希头进行索引每个哈希宏也都需要传入这个参数通常成为head哈希键值对 - 表示哈希结构申明的指针变量例如 example_user_t *user;
宏名用法含义HASH_ADD_INTusage:[ HASH_ADD_INT(head, id, user) ]在head增加一个INT键变量id所对应的键值对结构该结构内容为userHASH_FIND_INTusage:[ HASH_FIND_INT(head, user_id, user) ]在head查找INT类型键变量的值user_id所对应的键值对结构userHASH_DELusage:[ HASH_DEL(head, user)]删除head中键值对结构为user的键值对结构
uthash INT 示例代码学生管理系统
1. 整体思路如下 创建一个哈稀表完成 int 类型到 StudentInfo 结构体的映射。即 { int: StudentInfo }; 实现CRUD增删改查功能
2. 结构设计
// 既然使用hash表首先建立哈希表结构体[int, StudentInfo, UT_hash_handle]
// UT_hash_handle 是建立哈希索引和调用哈希宏所必须的结构体
// 再增加StudentInfo结构体本案例的内容只有name 和 examPerform名字和成绩这可以根据应用场景需要进行额外增加。
// 最后建立g_Class的全局变量用于存放哈希表表头。
typedef struct StudentInfo {char name[50];int examPerform;
} StudentInfo;typedef struct peopleManger_int {int id;StudentInfo *stuInfo;UT_hash_handle hh;
} peopleManger_int;/* 全局变量作为哈稀表 */
peopleManger_int *g_Class;3. uthash函数封装
// 因为我们哈希表的键为int型。因此用到的核心宏是
// HASH_ADD_INT usage:[ HASH_ADD_INT(哈希表头键变量名当前增加哈希结构)]
// HASH_FIND_INT usage:[ HASH_FIND_INT(哈希表头键变量的值用于存放当前当前增加哈希结构)]
// HASH_DEL usage:[ HASH_DEL(哈希表头需要删除的值变量的指针)]
// -------------------------------------------------------------------------------------
// 这里的 **item 是外部申明的值变量指针在内部进行申请内存因此需要采用双指针表示地址的形式。
static void __createStudent(peopleManger_int **item, int stuID)
{*item (peopleManger_int *)malloc(sizeof(peopleManger_int));(*item)-id stuID;HASH_ADD_INT(g_Class, id, *item);}// 这里可以看出查找HASH_FIND_INT时候通常会先申请一个空的哈希结构item然后将全局哈希头中键变量ID的对应的hash结构传给item
static peopleManger_int * __findStudent(int stuID)
{peopleManger_int *item NULL;HASH_FIND_INT(g_Class, stuID, item);return item;
}// 哈希删除之后需要释放堆上的空间。
static void __deleteStudent(peopleManger_int *item)
{HASH_DEL(g_Class, item);free(item-stuInfo);free(item);
}4. 增删改查
// 基于上述封装函数我们可以完成增删改查四个接口
/* 增 */
int pm_createStudent(int stuID, char *stuName, int exam)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem ! NULL) {printf(has student already, please use update\n);return -1;}__createStudent(pmHashItem, stuID);/* 学生信息的填充 */pmHashItem-stuInfo (StudentInfo *)malloc(sizeof(StudentInfo));memcpy(pmHashItem-stuInfo-name, stuName, sizeof(char) * (strlen(stuName) 1));pmHashItem-stuInfo-examPerform exam;return 0;
}/* 删 */
int pm_deleteStudent(int stuID)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem NULL) {printf(can not find item: %d\n, stuID);return -1;}__deleteStudent(pmHashItem);printf(stuID %d delete successfully\n);return 0;
}/* 改 */
int pm_updateStudent(int stuID, char *stuName, int exam)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem NULL) {printf(dont have student already, please use create\n);return -1;}pmHashItem-id stuID;memset(pmHashItem-stuInfo-name, 0, sizeof(char) * 50);memcpy(pmHashItem-stuInfo-name, stuName, sizeof(char) * (strlen(stuName) 1));pmHashItem-stuInfo-examPerform exam;return 0;
}/* 查找 */
int pm_readStudent(int stuID)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem NULL) {printf(can not find item: %d\n, stuID);return -1;}printf(stu id: %d | , pmHashItem-id);printf(stu name: %s | , pmHashItem-stuInfo-name);printf(stu exam: %d\n, pmHashItem-stuInfo-examPerform);return 0;
}5.遍历打印所有元素
void pm_printStudentName()
{peopleManger_int *pmHashItem NULL;for (pmHashItem g_Class; pmHashItem ! NULL; pmHashItem (peopleManger_int *)(pmHashItem-hh.next)) {printf(stu %d, name %s, exam %d\n, pmHashItem-id, pmHashItem-stuInfo-name, pmHashItem-stuInfo-examPerform);}
}6. 完整代码
#include stdio.h
#include string.h
#include ctype.h
#include uthash.htypedef struct StudentInfo {char name[50];int examPerform;
} StudentInfo;typedef struct peopleManger_int {int id;StudentInfo *stuInfo;UT_hash_handle hh;
} peopleManger_int;/* 全局变量作为哈稀表 */
peopleManger_int *g_Class;static void __createStudent(peopleManger_int **item, int stuID)
{*item (peopleManger_int *)malloc(sizeof(peopleManger_int));(*item)-id stuID;HASH_ADD_INT(g_Class, id, *item);}static peopleManger_int * __findStudent(int stuID)
{peopleManger_int *item NULL;HASH_FIND_INT(g_Class, stuID, item);return item;
}static void __deleteStudent(peopleManger_int *item)
{HASH_DEL(g_Class, item);free(item-stuInfo);free(item);
}/* 增 */
int pm_createStudent(int stuID, char *stuName, int exam)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem ! NULL) {printf(has student already, please use update\n);return -2;}__createStudent(pmHashItem, stuID);pmHashItem-stuInfo (StudentInfo *)malloc(sizeof(StudentInfo));memcpy(pmHashItem-stuInfo-name, stuName, sizeof(char) * (strlen(stuName) 1));pmHashItem-stuInfo-examPerform exam;return 0;
}/* 删 */
int pm_deleteStudent(int stuID)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem NULL) {printf(can not find item: %d\n, stuID);return -1;}__deleteStudent(pmHashItem);printf(stuID %d delete successfully\n);return 0;
}/* 改 */
int pm_updateStudent(int stuID, char *stuName, int exam)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem NULL) {printf(dont have student already, please use create\n);return -2;}pmHashItem-id stuID;memset(pmHashItem-stuInfo-name, 0, sizeof(char) * 50);memcpy(pmHashItem-stuInfo-name, stuName, sizeof(char) * (strlen(stuName) 1));pmHashItem-stuInfo-examPerform exam;return 0;
}/* 查找 */
int pm_readStudent(int stuID)
{peopleManger_int *pmHashItem NULL;pmHashItem __findStudent(stuID);if (pmHashItem NULL) {printf(can not find item: %d\n, stuID);return -1;}printf(stu id: %d | , pmHashItem-id);printf(stu name: %s | , pmHashItem-stuInfo-name);printf(stu exam: %d\n, pmHashItem-stuInfo-examPerform);return 0;
}void pm_printStudentName()
{peopleManger_int *pmHashItem NULL;for (pmHashItem g_Class; pmHashItem ! NULL; pmHashItem (peopleManger_int *)(pmHashItem-hh.next)) {printf(stu %d, name %s, exam %d\n, pmHashItem-id, pmHashItem-stuInfo-name, pmHashItem-stuInfo-examPerform);}
}int main()
{int i;peopleManger_int *stu NULL;/* create elements */printf(-----create element-----\n);for(i 0; i 10; i) {char name[10] a_xiao;name[0] a i;printf(here);pm_createStudent(i, name, 90 i);}printf(-----read element-----\n);for(stug_Class; stu ! NULL; stu(peopleManger_int *)(stu-hh.next)) {printf(stu %d, name %s, exam %d\n, stu-id, stu-stuInfo-name, stu-stuInfo-examPerform);}printf(delete a, go over\n);pm_deleteStudent(0);printf(-----read element-----\n);pm_printStudentName();pm_updateStudent(1, xiaoming, 99);pm_updateStudent(0, xiaohua, 99);pm_readStudent(1);pm_readStudent(0);return 0;
}