Linux散列表(一)——操作函数
散列表(又名哈希表)仅仅需要一个包含单一指针的链表头。它是双向链表的变体。它不同于双链表——表头和结点使用相同的结构体——散列表对表头和结点有不同的定义。如下:
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
散列表的实现一般采用hlist_head数组,每个hlist_head挂一个双向hlist_node链表,大致如下图。其中pprev它指向前一个结点的next指针。
1、初始化
1.1、初始化头
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
1.2、初始化结点
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
2、逻辑判断
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
3、删除结点
3.1、内部API
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;//(1)
struct hlist_node **pprev = n->pprev;//(2)
*pprev = next;//(3)
if (next)
next->pprev = pprev;//(4)
}
3.2、外部API
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);//(1)
n->next = LIST_POISON1;//(2)
n->pprev = LIST_POISON2;//(3)
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);//(1)
INIT_HLIST_NODE(n);//(2)
}
}
4、添加结点
4.1、表头添加结点
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)(0)
{
struct hlist_node *first = h->first;//(1)
n->next = first;//(2)
if (first)
first->pprev = &n->next;//(3)
h->first = n;//(4)
n->pprev = &h->first;//(5)
}
在此基础上再次插入一个结点
4.2、指定结点之前添加结点
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)//(0)
{
n->pprev = next->pprev;//(1)
n->next = next;//(2)
next->pprev = &n->next;//(3)
*(n->pprev) = n;//(4)
}
4.3、指定结点之后添加结点
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)//(0)
{
next->next = n->next;//(1)
n->next = next;//(2)
next->pprev = &n->next;//(3) if(next->next)
next->next->pprev = &next->next;//(4)
}
/* after that we'll appear to be on some hlist and hlist_del will work */
static inline void hlist_add_fake(struct hlist_node *n)
{
n->pprev = &n->next;
}
5、移动散列表
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;//(1)
if (new->first)
new->first->pprev = &new->first;//(2)
old->first = NULL;//(3)
}
Linux散列表(一)——操作函数的更多相关文章
- Linux散列表(二)——宏
散列表宏承接了双向链表宏的风范,好使好用!务必区分“结点”和“元素”!双链表宏博文中已经提及,这里不赘述! 1.获取元素(结构体)基址 #define hlist_entry(ptr, type, m ...
- python字符串 列表 元组 字典相关操作函数总结
1.字符串操作函数 find 在字符串中查找子串,找到首次出现的位置,返回下标,找不到返回-1 rfind 从右边查找 join 连接字符串数组 replace 用指定内容替换指定内容,可以指定次数 ...
- VC散列表
vc下有2个版本的散列表类,hash_map和unordered_map,hash_map位于stdext命名空间,unordered_map在std命名空间(vs2008及其之后的版本可用),官方推 ...
- 散列表Java实现
package 散列表; import java.util.Scanner; public class HashSearch { public static int data[] = {69,65,9 ...
- 10-10Linux的文件操作函数以及所需头文件
Linux的基本文件操作函数 Linux通过相应的对文件的IO函数来实现对文件的操作,这些函数通常被称作"不带缓冲的IO",这是因为他们都是通过调用Linux的内核调用来实 ...
- linux内核的双链表list_head、散列表hlist_head
一.双链表list_head 1.基本概念 linux内核提供的标准链表可用于将任何类型的数据结构彼此链接起来. 不是数据内嵌到链表中,而是把链表内嵌到数据对象中. 即:加入链表的数据结构必须包含一个 ...
- python对redis的常用操作 上 (对列表、字符串、散列结构操作)
这里的一切讨论均基于python的redis-py库. 安装使用: pip install redis 然后去获取一个redis客户端: redis_conn = redis.Redis(host=R ...
- Python 散列表查询_进入<哈希函数>为结界的世界
1. 前言 哈希表或称为散列表,是一种常见的.使用频率非常高的数据存储方案. 哈希表属于抽象数据结构,需要开发者按哈希表数据结构的存储要求进行 API 定制,对于大部分高级语言而言,都会提供已经实现好 ...
- [Linux] Linux进程PID散列表
linux系统中每个进程由一个进程id标识,在内核中对应一个task_struct结构的进程描述符,系统中所有进程的task_struct通过链表链接在一起,在内核中,经常需要通过进程id来获取进程描 ...
随机推荐
- HttpClient的get+post请求使用
啥都不说,先上代码 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReade ...
- throw 导致 Error C2220, wraning C4702错误
今天在程序加了一个语句,发现报 Error C2220, Wraning C4702错误 查询Wraning C4702 ,[无法访问的代码] 由于为 Visual Studio .NET 2003 ...
- java中处理http连接超时的方法
声明一个boolean公共变量,表明当前httpconnection是否得到服务器回应. 你的连接线程中在连接之前置这个变量为false; 另起一个监视线程,拿到那个HttpConnection的连接 ...
- 导出Excel后其他按钮失效
在SharePoint中,当在页面上点击Export to Excel按钮后,第一次它能实现该功能,当再次点击该按钮时,页面上的所有按钮将失效,仅仅再次刷新该页面时按钮才会有效,首先想到出现该问题肯定 ...
- api1
http://www.android-doc.com/reference/android/app/Fragment.html
- frame,bounds,center-三者的含义
frame与bounds的区别比较 frame,bounds,center-三者的含义 偶然觉的,这三个属性有时候定位的时候,需要用.于是就来搞清楚,到底frame,bounds,center 这三个 ...
- Swift中KIF测试的特点-b
我最近在忙着回归到过去测试代码的老路子,使用KIF和XCTest框架,这样会使得iOS中的测试变得简单.当我开始捣鼓KIF的时候,我用Swift写的应用出了点小问题,不过最终还是很机智的搞定了.在我写 ...
- HTML5 display:inline、block、inline-block的区别--备用
display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...
- BZOJ 1022 小约翰的游戏
Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...
- 我的VSTO之路(二):VSTO程序基本知识
原文:我的VSTO之路(二):VSTO程序基本知识 开始之前,首先我介绍一下我的开发环境:VS2010 + Office 2010,是基于.Net framework 4.0和VSTO 4.0.以下的 ...