• C函数学习(1):uthash哈希表


    1 哈希表简介

    哈希表是一种基于key-value进行访问的数据结构,可以加快查找的速度,因此在一些需要快速查找是否有重复元素的场景中,常常使用哈希表来实现。

    2 uthash

    C语言中不存在哈希,如果自己构建则会很麻烦。第三方开源的代码中已经实现哈希表,因此我们在使用中只需要包含头文件“uthash.h”即可使用第三方的哈希功能。

    PS:uthash还包括三个额外的头文件,主要提供链表,动态数组和字符串。utlist.h为C结构提供了链接列表宏。utarray.h使用宏实现动态数组。utstring.h实现基本的动态字符串。

    下载链接:https://github.com/troydhanson/uthash
    文档说明:http://troydhanson.github.io/uthash/userguide.html#_find_item

    2.1 定义结构体

    在使用时候我们需要先定义一个结构体。如下:

    typedef struct _HashTable_
    {
    	int s32Key;      //key
    	int s32Value;
        UT_hash_handle hh;
    }HastTableST;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在上面的结构体中,s32Key就是键;
    s32Value是我们自定义的值,用来存放私有的数据,可以根据自己的需要定义;
    hh是内部使用的hash处理句柄,在使用过程中,只需要在结构体中定义一个UT_hash_handle类型的变量即可,不需要为该句柄变量赋值,但必须在该结构体中定义该变量。

    键的类型不一定是int类型,也可以是字符串类型,指针类型和任意类型,不同类型的键在下面插入,查找使用的函数宏是不一样的。

    2.2 键类型为int

    2.2.1 插入

    HASH_ADD_INT
    
    • 1

    2.2.2 查找

    HASH_FIND_INT
    
    • 1

    2.2.3 删除

    HASH_DEL
    
    • 1

    2.2.4 替换

    HASH_REPLACE_INT
    
    • 1

    2.2.5 计数

    HASH_COUNT
    
    • 1

    2.2.6 遍历

    HASH_ITER
    
    • 1

    2.2.7 示例

    #include 
    //#include "uthash.h"
    
    typedef struct _HashTable_
    {
    	int s32Key;
    	int s32Index;       //用户自定义的值
    	UT_hash_handle hh;
    }HastTableST;
    
    //清除单个
    void hash_clearsingle(HastTableST* pstHash, HastTableST* pstDelHash)
    {
    	HASH_DEL(pstHash, pstDelHash);
    	free(pstDelHash);
    	pstDelHash = NULL;
    }
    
    //清除全部
    void hash_clearall(HastTableST* pstHash)
    {
    	HastTableST *s, *tmp;
    	HASH_ITER(hh, pstHash, s, tmp)
    	{
    		HASH_DEL(pstHash, s);
    		free(s);
    		s = NULL;
    	}
    }
    //查找
    HastTableST* hash_find(HastTableST* pstHash, int s32Key)
    {
    	HastTableST* pstTmpHash = NULL;
    	
    	HASH_FIND_INT(pstHash, &s32Key, pstTmpHash);
    	
    	return pstTmpHash;
    }
    
    //添加
    void hash_add(HastTableST* pstHash, int s32KKey)
    {
    	HastTableST* pstTmpHash = NULL;
    	
    	pstTmpHash = hash_find(pstHash, s32KKey); //先查找key是否存在哈希表中
    	if (NULL == pstTmpHash)
    	{
    		pstTmpHash = (HastTableST *)malloc(sizeof(HastTableST));
    		pstTmpHash->s32Key = s32KKey;
    		HASH_ADD_INT(pstHash, s32Key, pstTmpHash);
    	}
    	else  //存在
    	{
    		
    	}
    }
    
    //替换
    //HASH_REPLACE_INT
    
    
    //计数
    int hash_count(HastTableST* pstHash)
    {
    	return HASH_COUNT(pstHash);
    }
    
    //遍历
    void hash_iter(HastTableST* pstHash)
    {
    	HastTableST *s, *tmp;
    	HASH_ITER(hh, pstHash, s, tmp)
    	{
    		printf("user id %d\n", s->s32Key);
    		/* ... it is safe to delete and free s here */
    	}
    }
    
    int main()
    {
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    2.3 键类型为字符串

    除了查找(HASH_FIND_STR)和添加( HASH_ADD_KEYPTR),其它函数一致。

    示例:

    #include 
    //#include "uthash.h"
    
    typedef struct _HashTable_
    {
    	char* s8Name;
    	int s32Index;       //用户自定义的值
    	UT_hash_handle hh;
    }HastTableST;
    
    //清除单个
    void hash_clearsingle(HastTableST* pstHash, HastTableST* pstDelHash)
    {
    	HASH_DEL(pstHash, pstDelHash);
    	free(pstDelHash);
    	pstDelHash = NULL;
    }
    
    //清除全部
    void hash_clearall(HastTableST* pstHash)
    {
    	HastTableST *s, *tmp;
    	HASH_ITER(hh, pstHash, s, tmp)
    	{
    		HASH_DEL(pstHash, s);
    		free(s);
    		s = NULL;
    	}
    }
    
    //查找
    HastTableST* hash_find(HastTableST* pstHash, char* s8Key)
    {
    	HastTableST* pstTmpHash = NULL;
    	
    	HASH_FIND_STR(pstHash, s8Key, pstTmpHash);
    	
    	return pstTmpHash;
    }
    
    //添加
    void hash_add(HastTableST* pstHash, char* s8Key)
    {
    	HastTableST* pstTmpHash = NULL;
    	
    	pstTmpHash = hash_find(pstHash, s8Key); //先查找key是否存在哈希表中
    	if (NULL == pstTmpHash)
    	{
    		pstTmpHash = (HastTableST *)malloc(sizeof(HastTableST));
    		pstTmpHash->s8Name = s8Key;
    		HASH_ADD_KEYPTR(hh, pstHash, pstTmpHash->s8Name, strlen(pstTmpHash->s8Name), pstTmpHash);
    	}
    	else  //存在
    	{
    		
    	}
    }
    
    //替换
    //HASH_REPLACE_INT
    
    
    //计数
    int hash_count(HastTableST* pstHash)
    {
    	return HASH_COUNT(pstHash);
    }
    
    //遍历
    void hash_iter(HastTableST* pstHash)
    {
    	HastTableST *s, *tmp;
    	HASH_ITER(hh, pstHash, s, tmp)
    	{
    		printf("user id %s\n", s->s8Name);
    		/* ... it is safe to delete and free s here */
    	}
    }
    
    int main()
    {
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    2.4 键类型为指针

    除了添加(HASH_ADD_PTR)和查找( HASH_FIND_PTR),其它函数一致。

    示例:

    #include 
    //#include "uthash.h"
    
    typedef struct _HashTable_
    {
    	void* pKey;
    	int s32Index;       //用户自定义的值
    	UT_hash_handle hh;
    }HastTableST;
    
    //清除单个
    void hash_clearsingle(HastTableST* pstHash, HastTableST* pstDelHash)
    {
    	HASH_DEL(pstHash, pstDelHash);
    	free(pstDelHash);
    	pstDelHash = NULL;
    }
    
    //清除全部
    void hash_clearall(HastTableST* pstHash)
    {
    	HastTableST *s, *tmp;
    	HASH_ITER(hh, pstHash, s, tmp)
    	{
    		HASH_DEL(pstHash, s);
    		free(s);
    		s = NULL;
    	}
    }
    //查找
    HastTableST* hash_find(HastTableST* pstHash, void* pFindKey)
    {
    	HastTableST* pstTmpHash = NULL;
    	
    	HASH_FIND_PTR(pstHash, &pFindKey, pstTmpHash);
    	
    	return pstTmpHash;
    }
    
    //添加
    void hash_add(HastTableST* pstHash, void* pFindKey)
    {
    	HastTableST* pstTmpHash = NULL;
    	
    	pstTmpHash = hash_find(pstHash, pFindKey); //先查找key是否存在哈希表中
    	if (NULL == pstTmpHash)
    	{
    		pstTmpHash = (HastTableST *)malloc(sizeof(HastTableST));
    		pstTmpHash->pKey = pFindKey;
    		HASH_ADD_PTR(pstHash, pKey, pstTmpHash);
    	}
    	else  //存在
    	{
    		
    	}
    }
    
    //替换
    //HASH_REPLACE_INT
    
    
    //计数
    int hash_count(HastTableST* pstHash)
    {
    	return HASH_COUNT(pstHash);
    }
    
    //遍历
    void hash_iter(HastTableST* pstHash)
    {
    	HastTableST *s, *tmp;
    	HASH_ITER(hh, pstHash, s, tmp)
    	{
    		printf("user id %d\n", s->s32Key);
    		/* ... it is safe to delete and free s here */
    	}
    }
    
    int main()
    {
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    2.5 键类型为任意类型

    参考链接:http://troydhanson.github.io/uthash/userguide.html#_structure_keys

  • 相关阅读:
    Unity 2D SpriteRenderer filled Shader实现
    Intellij 安装配置 lombok
    java毕业设计基于Bootstrap的家具商城系统设计mybatis+源码+调试部署+系统+数据库+lw
    数字孪生政务丨构建大数据可视化展现平台,提高行政服务效能
    毕设准备---HelloServlet
    docker.4.2-Docker容器镜像
    JVM内存结构
    cobalt strike 的基础使用
    Maven
    各省份12.5m地形数据
  • 原文地址:https://blog.csdn.net/u011003120/article/details/124986557