Linux环境编程 哈希链表结构 hlist 介绍与用例
生活随笔
收集整理的這篇文章主要介紹了
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 内核抓包功能实现基础(四)