我的glib学习之旅从哈希表开始。了解到了glib库这个很方便强大的库,正巧写程序的时候使用了一下,在这里做一次总结,基于glib-2.50.3源码。
       Glib提供了很多方便的功能,这一次主要用到glib提供的数据结构,哈希表,相关接口说明文档这里。
       哈希表所描述的是一种键值对的对应关系,通过给定的key,能够快速的找到对应的value。也就是说哈希表表达的是key到value的映射关系。这一次着重说明一下如何使用glib为管理哈希表提供的接口。
       通常对于一个哈希表的操作包括,创建哈希表,删除哈希表以及对于哈希表每一个条目的增删改查等。这里面最大的一个陷阱在于内存的回收方面,下面也有重点提及。毕竟对于在哈希表的实现方面,管理内存是很重要的。
创建一个哈希表:
       由于C语言没有函数重载的功能,可以看到glib提供如下两个创建哈希表的接口函数:

GHashTable *g_hash_table_new(GHashFunc hash_func, GEqualFunc key_equal_func);GHashTable* g_hash_table_new_full(GHashFunc hash_func,GEqualFunc key_equal_func,
GDestroyNotify key_destroy_func,GDestroyNotify value_destroy_func);

g_hash_table_new_full函数中四个参均是函数指针,其的意义如下:hash_func函数是将key值转换成为key_hash,这里面key_hash通常是一个无符号的整形,而value值的索引则是将key_hash模除哈希表的大小;由于key的值则可能是数字,字符串,结构体,因此我通常的做法是把key这段内存空间按照8字节拼接起来,形成一个字符串,然后由g_str_hash生成对应的哈希值。key_equal_func函数是比较key值的函数,在插入删除等操作的时候都会用到该函数。因为key值可能是整数,字符串或者结构体,因此比较不同类型数据是否相同的的方法在该函数内实现。key_destroy_func是key值内存的释放函数。value_destroy_func是value值内存的释放函数。key_destroy_func以及value_destroy_func是容易出现错误的地方,在删除哈希表条目的时候再提。g_hash_table_new 函数就是默认的key_destroy_func 和value_destroy_func的值为NULL。
删除一个哈希表:
       函数接口是void g_hash_table_destroy (GHashTable *hash_table)。C语言常见的问题之一就是内存泄露问题。这时候上述所提到的key_destroy_func函数以及value_destroy_func函数的作用就出来了,主要是针对key和value所指向的内存是动态申请的。这两个函数的作用就是定义如何释放key和value对应的内存空间,在调用g_hash_table_destroy函数的时候会触发key_destroy_func以及value_destroy_func函数。
增加哈希表条目:

gboolean
g_hash_table_insert (GHashTable *hash_table,gpointer key,gpointer value);

我一开始想当然的以为如果系统中存在,就会不插入该条目,然后就没有其他操作了,实际上,这里面就是一个坑,源码中还有其他的操作。向hash_table表中插入key和value。如果原来的哈希表中不存在相同的key,那么直接插入没有问题;如果原来哈希表中存在一样的key的话,则触发key_destroy_func函数释放传递进来参数key所代表的空间,同时释放哈希表中老value空间,并将传递进来新的value加入到哈希表中,这样可以保证哈希表中存在的是最新的value值。这和后面的g_hash_table_replace修改哈希条目是有所不同的。这个时候如果key是常量字符串等存储在全局数据区的话,释放时候就会发生错误;另外如果key值是value值的一部分的话,也可能会出错。
删除哈希表条目:

gboolean g_hash_table_remove (GHashTable *hash_table,gconstpointer key);

删除hash_table表中key值所表示的一条记录,这时候同样会触发key_destroy_func函数以及value_destroy_func函数。其实删除整个哈希表也是一步步释放哈希表的每一个条目的。
修改哈希表条目:

gboolean
g_hash_table_replace (GHashTable *hash_table,gpointer key,gpointer value);

该函数提供修改key值所对应value值的操作,如果哈希表中不存在该key值,则该函数跟g_hash_table_insert的功能一致;如果哈希表中存在相同的key值,和g_hash_table_insert的区别在于,触发key_destroy_func函数释放哈希表中老key所代表的空间,并将传递进来新的key加入到哈希表中;同时触发value_destroy_func函数释放哈希表中老的value空间,并将传递进来新的value加入到哈希表中。
查找哈希表条目:

gpointer g_hash_table_lookup (GHashTable *hash_table,gconstpointer key)

查找相同的key,返回对应的value指针地址,找不到则为NULL。
遍历哈希表:

g_hash_table_iter_init (&iter, hash_table);
while (g_hash_table_iter_next (&iter, &key, &value)){// do something with key and value}

这个接口文档给出的事例,如果了解遍历器,这里应该很好理解。
       综上,在使用哈希表的时候,关于key_destroy_func 和value_destroy_func函数的编写以及使用要注意两点:1、传参的时候,不要传入在全局数据区的变量,因为这两个释放函数是针对动态申请内存的。2、key最好和value相互独立,从上面的分析可以看出,如果key是value的一部分,则很有可能会出现错误。
       另外glib的哈希表解决地址冲突的方法不像我们当时课本上面以及通常大家使用的链表方式,而是基于数组的。数组的优势就是一块连续的内存空间,因此在按照现有的计算机缓存结构来说,访问效率更高。因此下一步是研究一下glib是如何设计实现哈希表的。
       本文为CSDN村中少年原创文章,转载记得加上小尾巴偶,博主链接这里。

glib使用之哈希表相关推荐

  1. 【C#】集合_哈希表_字典_泛型_文件

    数组能做到:存放同种类型数据,且数据个数确定 object类型的数组能满足:放各种类型的数据,确定放多少个,但是随意插入元素,数组做不到 集合能做到:存放各种数据类型,且不确定存放多少个,能做到随意插 ...

  2. PHP哈希表碰撞攻击原理

    哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招.本文结合PHP内核源码,聊一聊这种攻击的原理及实现. 哈希表碰撞攻击的基本原理 ...

  3. 在C#中应用哈希表(Hashtable)

    一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其 ...

  4. 自己写的哈希表以及解决哈希冲突

    哈希表就是键值key-value对,使用hash函数让key产生哈希值,当不同的key产生相同的哈希值时就是哈希冲突了,产生哈希冲突可以使用拉链法. hash.c #include <stdio ...

  5. PHP内核中的哈希表结构

    https://github.com/HonestQiao/tipi/commit/17ca680289e490763a6a402f79afa2a13802bb36 下载:https://github ...

  6. 用开放地址法中的线性探查法解决冲突实现哈希表的运算

    为了更深的理解哈希算法,自己写了用开放地址法中的线性探查法解决冲突实现哈希表的运算. /*** Created by lirui on 14-8-13.* 用开放地址法中的线性探查法解决冲突实现哈希表 ...

  7. 散列表查找(哈希表)

    散列函数构造经常要考虑: 1.散列表的长度 2.关键字的长度 3.关键字的分布情况 4.计算散列函数所需的时间 5.记录的查找频率 一个"好"的散列函数应遵循一下两条原则 (1)函 ...

  8. 不同表结构数据迁移_数据结构:哈希 哈希函数 哈希表

    写在前面 希望你们看了能够有所收获,同时觉得不错的朋友可以点赞和关注下我,以后还会有更多精选文章分享给大家!大家可以关注一下java提升专栏 java提升​zhuanlan.zhihu.com 什么是 ...

  9. 【数据结构】 哈希表 详解

    目录 1. 概念 引入 2. 冲突 2.1 概念 2.2 避免 2.3 冲突-避免-哈希函数设计 2.4 冲突-避免-负载因子调节(重点) 2.5 冲突-解决 2.5.1 闭散列 2.6 冲突-解决- ...

  10. 数组-丢失的数字(哈希表法)

    题意: 给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数. 示例 1: 输入:nums = [3,0,1] 输出:2 解释:n = 3 ...

最新文章

  1. 如何判断一个对话机器人有多智能?
  2. 【612页】Android 大厂面试题及解析大全(中高级)
  3. Frameless - 用于预览 iOS8 原型的浏览器
  4. OpenGL HDR曝光的实例
  5. Ajax获取XML格式的数据
  6. VMWare虚拟机NAT上网方法 亲测可用
  7. 创建一个学生信息表,与页面分离
  8. 技能学习重要的古语_学习方法:最重要的开发人员技能
  9. [转载] python中集合的表示_Python No.18_集合以及表示符号
  10. atoi函数:c\c++中把字符串整数转换为int型整数
  11. node.js学习文档_学习NodeJs从每天一个小知识点开始
  12. uclient uc oracle,UClient下载
  13. 计算机科学基础慕课答案,大学计算机基础mooc习题整理(含答案)
  14. 非度量多维标度_非度量多维尺度分析
  15. 计算机配置路径,计算机基础~Windows工作路径、相对路径、绝对路径
  16. VGA、DVI、HDMI都是什么意思?
  17. 抽奖游戏 js php,jQuery实现简单的抽奖游戏技术分享
  18. 解决谷歌浏览器chrome的CPU占用率过高的问题
  19. QT将10进制转换为2进制与16进制
  20. 【Java开发 | 工具使用】JAVA使用exe4j打包项目为exe文件

热门文章

  1. Lambda将搬砖变成艺术
  2. ABAP SPLITTER技术总结及使用技巧
  3. 瑞萨 报错 Section “.monitor2“ overlaps section “.textf“
  4. amap_flutter_map 初始化地图后将当前位置设为地图的中心点
  5. Affine set 和 convex set 的定义
  6. matplotlib折线图(标记点、标记点大小、标记点边颜色、标记点边宽)
  7. 数据分析-美国小孩英文名分析-可视化(含代码)
  8. 程序员必备的七个电脑软件
  9. RobotStudio 示教器编程:MoveC指令
  10. python-文件读写-OS-窗口控制