散列表(又名哈希表)仅仅需要一个包含单一指针的链表头。它是双向链表的变体。它不同于双链表——表头和结点使用相同的结构体——散列表对表头和结点有不同的定义。如下:

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散列表(一)——操作函数的更多相关文章

  1. Linux散列表(二)——宏

    散列表宏承接了双向链表宏的风范,好使好用!务必区分“结点”和“元素”!双链表宏博文中已经提及,这里不赘述! 1.获取元素(结构体)基址 #define hlist_entry(ptr, type, m ...

  2. python字符串 列表 元组 字典相关操作函数总结

    1.字符串操作函数 find 在字符串中查找子串,找到首次出现的位置,返回下标,找不到返回-1 rfind 从右边查找 join 连接字符串数组 replace 用指定内容替换指定内容,可以指定次数 ...

  3. VC散列表

    vc下有2个版本的散列表类,hash_map和unordered_map,hash_map位于stdext命名空间,unordered_map在std命名空间(vs2008及其之后的版本可用),官方推 ...

  4. 散列表Java实现

    package 散列表; import java.util.Scanner; public class HashSearch { public static int data[] = {69,65,9 ...

  5. 10-10Linux的文件操作函数以及所需头文件

    Linux的基本文件操作函数     Linux通过相应的对文件的IO函数来实现对文件的操作,这些函数通常被称作"不带缓冲的IO",这是因为他们都是通过调用Linux的内核调用来实 ...

  6. linux内核的双链表list_head、散列表hlist_head

    一.双链表list_head 1.基本概念 linux内核提供的标准链表可用于将任何类型的数据结构彼此链接起来. 不是数据内嵌到链表中,而是把链表内嵌到数据对象中. 即:加入链表的数据结构必须包含一个 ...

  7. python对redis的常用操作 上 (对列表、字符串、散列结构操作)

    这里的一切讨论均基于python的redis-py库. 安装使用: pip install redis 然后去获取一个redis客户端: redis_conn = redis.Redis(host=R ...

  8. Python 散列表查询_进入<哈希函数>为结界的世界

    1. 前言 哈希表或称为散列表,是一种常见的.使用频率非常高的数据存储方案. 哈希表属于抽象数据结构,需要开发者按哈希表数据结构的存储要求进行 API 定制,对于大部分高级语言而言,都会提供已经实现好 ...

  9. [Linux] Linux进程PID散列表

    linux系统中每个进程由一个进程id标识,在内核中对应一个task_struct结构的进程描述符,系统中所有进程的task_struct通过链表链接在一起,在内核中,经常需要通过进程id来获取进程描 ...

随机推荐

  1. node http.request请求

    var http = require('http'); var querystring = require('querystring'); var path = '/cricket/getRecord ...

  2. LA 6474 Drop Zone (最小割)

    题目链接 要添最少的挡板使所有的'D'不存在到达网格外的路径. 以每个格子向四个方向中可以到达的格子连容量为1的边, 从源点向所有'D' 连容量为4的边,网格外的点向汇点连一条容量为4的边. 答案就是 ...

  3. 【HDU4010】【LCT】Query on The Trees

    Problem Description We have met so many problems on the tree, so today we will have a query problem ...

  4. 使用require.js时,解决AMD封装jquery1.4.1的问题。

    require.config({ baseUrl: "js/", paths: { "jquery": "jquery-1.4.1.min" ...

  5. Bootstrap_表单_图像

    在Bootstrap框架中对于图像的样式风格提供以下几种风格: 1.img-responsive:响应式图片,主要针对于响应式设计2.img-rounded:圆角图片3.img-circle:圆形图片 ...

  6. 去除后台ckeditor的style="...."的样式

    .cnt_text .text img {/*width :auto !important;*/height :auto !important; max-width:660px;} 高度自适应,高度让 ...

  7. JS设置Cookie,及COOKIE的限制

    在Javascript脚本里,一个cookie 实际就是一个字符串属性.当你读取cookie的值时,就得到一个字符串,里面当前WEB页使用的所有cookies的名称和值.每个cookie除了 name ...

  8. PHP常用函数和常量

    PHP常用系统常量 __FILE__ 文件的完整路径和文件名.如果用在被包含文件中,则返回被包含的文件名.自 PHP 4.0.2 起,总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径),而在 ...

  9. mysql oracle 删除外键约束

    mysql alter table xxx drop foreign key xxx cascade; oracle alter table drop constraint xxxxx cascade ...

  10. 初始化rails上的compass项目

    compass以外还有一个很实用的scss模块, _media-queries.scss 通过终端下载 curl -O https://raw.github.com/paranoida/sass-me ...