Linux环境编程 哈希链表结构 hlist 介绍与用例
hlist原本是定义在内核list.h里面的结构体,主要用在解决哈希表冲突时使用链接(chaining)方法时候用到的结构体。结构体定义简单、相关的接口也比较丰富,可以直接拿到用户层使用。最常见的一种使用场景如下图:
htable是hash数组,每个数组元素是一个hlist_head结构体。当多个结点的hash key值相同时,直接添加在对应的结点链表里就可以了。下面介绍相关数据结构和操作接口使用。
链表头和结点的结构体定义:
/* 链表头 */
struct hlist_head {struct hlist_node *first;
};/* 链表结点,具体的数据结构体只需要包含这个结构体就可以了 */
struct hlist_node {struct hlist_node *next, **pprev;
};
链表头和结点使用前需要初始化:
//hlist_head 初始化
#define HLIST_HEAD_INIT { .first = NULL } //静态初始化
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) //动态初始化//hlist_node 初始化
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{h->next = NULL;h->pprev = NULL;
}
常用接口包括添加、删除和修改:
//添加结点至链表首部
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h);
//删除前有判断
static inline void hlist_del_init(struct hlist_node *n);
//判断链表头是否为空,是的话返回1
static inline int hlist_empty(const struct hlist_head *h);
//遍历结点
hlist_for_each(pos, head) //遍历结点过程中有删除结点操作使用这个接口
hlist_for_each_safe(pos, n, head)
//遍历获取结点里的数据
hlist_for_each_entry(tpos, pos, head, member)
//遍历结点过程中有删除结点操作使用这个接口
hlist_for_each_entry_safe(tpos, pos, n, head, member)
假设结点结构体定义如下;
//结点结构体
struct hdata_node {unsigned int data;struct hlist_node list;
};
下面是一个小李子,采用除法散列法计算hash值,结点定义如上,包含添加、删除和查询操作。
/** Description : linux应用层编程之哈希链表hlist的使用* Date :20180713* Author :fuyuande* Mail : mrsonko@126.com**/#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>#include "hlistdemo.h"#define log(fmt, arg...) printf(""fmt,##arg)
#define MAX_ADDR 256void main(int argc, char **argv){struct hlist_head htable[MAX_ADDR]; //hash数组struct hdata_node *hnode = NULL;struct hlist_node *hlist = NULL, *n = NULL;int i = 0, quit = 1, opt = 0, key;unsigned int data;/* hlist_head 动态初始化 */for(i = 0; i < MAX_ADDR; i++) //hash数组动态初始化INIT_HLIST_HEAD(&htable[i]);log("*********************\n\n""input options:\n""1: insert\n" //插入"2: serach\n" //查询"3: delete\n" //删除"0: quit\n""\n*********************\n"); while(quit != 0){log("\ninput options:");scanf("%d", &opt);switch(opt){//插入case 1://分配结点hnode = calloc(1, sizeof(struct hdata_node));if(!hnode){log("insert fail \n");break;}//hlist_node 结点初始化INIT_HLIST_NODE(&hnode->list);log("\ninput data:");scanf("%d", &hnode->data);key = hnode->data % MAX_ADDR;//添加到链表首部hlist_add_head(&hnode->list, &htable[key]);break;//查询case 2:log("\ninput data:");scanf("%d", &data); key = data % MAX_ADDR;if(hlist_empty(&htable[key]))log("data not exist \n");else{//遍历对应的槽位,匹配值就打印hlist_for_each_entry(hnode, hlist, &htable[key], list){if(hnode->data == data)log("find data : %u \n", hnode->data);}} break;//删除case 3:log("\ninput data:");scanf("%d", &data); key = data % MAX_ADDR;if(hlist_empty(&htable[key]))log("data not exist ,delete fail \n");else{//遍历对应的槽,匹配值就删除hlist_for_each_entry_safe(hnode, hlist, n, &htable[key], list){if(hnode->data == data){hlist_del(&hnode->list);break;}}} log("delete fail\n"); break;case 0:quit = 0;break;default:log("unrecognized option!");break; }}//退出程序前释放资源for(i=0; i < MAX_ADDR; i++){//遍历每一个槽,有结点就删除hlist_for_each_entry_safe(hnode, hlist, n, &htable[i], list){ hlist_del(&hnode->list); log("delete %u \n", hnode->data);free(hnode);hnode = NULL;}}log("exit\n");
}
代码放在:git@github.com:FuYuanDe/hlist_demo.git
git clone之后直接make运行。
またね!
Linux环境编程 哈希链表结构 hlist 介绍与用例相关推荐
- 林世霖. linux环境编程图文指南,linux环境编程图文指南
linux环境编程图文指南是一本linux编程环境配置指南,由林世霖.钟锦辉和李建辉三人共同编著.本书定位Linux环境编程入门与提高,全书拥有近400余幅案例图表,200多篇源代码,作者很多编程初入 ...
- linux 应用层编程之内核链表list的使用
linux内核提供了一个经典通用的双向循环链表list的实现,任何模块都可以借助该接口实现自己的内部循环链表.因为是通用的,可以直接移植到用户态中使用,下面介绍相关的接口与一个简单操作例子,包括链表的 ...
- Linux 环境编程 day01 Linux系统介绍、GNU编译工具、静态/共享库、环境变量表
Linux 环境编程 day01 Linux系统介绍.GNU编译工具.静态/动态库.环境变量表 学习Linux环境编程的原因 UNIX系统介绍 Linux系统介绍 GNU工程 POSIX标准 GNU通 ...
- linux环境编程从应用,linux环境编程:从应用到内核
<UNIX环境高级编程>(简称APUE)几乎是Linux领域程序员人手必备的一本书.但在掌握和理解APUE的内容后,又该如何继续提高自己的技能,如何更深入地理解Linux环境编程及其背后的 ...
- Linux环境编程(4)文件操作相关内容补充
Linux环境编程(4) 文件同步: 1.在写入数据时内存与磁盘之间也有一个缓冲区,这种机制降低了磁盘读写次数,提高了读写的效率. 2.但这种机制带来的后果就是磁盘中的数据与实写入的数据不匹配,系统提 ...
- Linux 环境编程 用户层定时器使用二 timer_create的使用
用户层定时器有两种,一种是timerfd,另一种是timer_create,前者比较新,使用比较方便. Linux环境编程 用户层定时器使用一 timerfd的使用 https://blog.csdn ...
- 嵌入式Linux系统编程学习之一目录结构
嵌入式Linux系统编程学习之一目录结构 文章目录 嵌入式Linux系统编程学习之一目录结构 前言 一.Linux目录结构 前言 Linux目录结构 一.Linux目录结构 /bin:存放Linux的 ...
- Linux环境编程05
目录 Linux环境编程05 一.信号相关基本概念 二.信号捕获 三.进程休眠信号 四.信号集和信号阻塞 五.附带数据信息的信号处理(较难) 六.定时器 Linux环境编程05 声明:本学习笔记为个人 ...
- Linux环境编程姜林美,Linux环境编程习题_编程题_答案.pdf
Linux环境编程习题_编程题_答案 Linux 境编程-人民邮电出版社-姜林美 课后习题(编程题)答案 第三章 1 第五章 4 第六章 9 第七章 19 第八章 22 第九章 35 第十章 38 三 ...
最新文章
- Android7.0以后的ninja编译系统
- java乘法代码_java九九乘法表代码
- 排名 教材 数字电子技术_数字电子技术教材改革及实践
- 面试自我介绍优秀范文
- python实用脚本(三)—— 通过有道智云API实现翻译
- 偏差、误差、训练误差、测试误差
- 【MATLAB】创建网格图和曲面图
- Arcgis10.8中将三维的高程点转换为二维的高程点
- KV存储相关基础知识
- 苹果设备如何进入恢复模式
- pitfall override private method
- java 枚举values()方法
- 21种优化产品转化率的设计技巧
- 【应用随机过程】04. 马尔可夫链的平稳分布
- 一篇文章普及各种ios基本知识
- 莫比乌斯函数(Mobius)的求法 每日一遍,算法再见!
- 未来计算机的特点是什么,【简答题】未来计算机的发展将会呈现以下几个趋势:...
- Ubuntu与ROS的Docker桌面系统与ROS在线练习课程(在线Linux虚拟机)
- 魔塔之拯救白娘子~我的第一个VB6+DX8做的小游戏源码~14开始游戏-流程处理
- 卡巴斯基CEO称勒索病毒为最严重的网络攻击之一
热门文章
- MERGE INTO
- 成功人士,默默做的30件事 (4-6)
- 篝火 2004 年11-15
- python优先队列_python实现最大优先队列
- 学python还是php2019_有2019年开始学PHP的人吗,可不可以分享一下你是如何考虑的?...
- 空间到底是什么?---車粒子
- python tushare获取股票数据_Python 金融: TuShare API 获取股票数据 (1)
- 【Paper】An Experiment Comparing Double Exponential Smoothing and Kalman Filter-Based Predict
- 【Matlab 控制】利用 Simulink 对微分代数方程建模
- 【数理知识】《随机过程》方兆本老师-第3章-Markov 过程