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来获取进程描 ...
随机推荐
- javascript基础学习(五)
javascript之函数 学习要点: 函数的介绍 函数的参数 函数的属性和方法 系统函数 一.函数的介绍 1.函数就是一段javascript代码.可以分为用户自定义函数和系统函数. 如果一个函 ...
- android查看真机中的数据库
0.在有网的前提下1.安装 Android Studio,Lantern,Chrome浏览器2.在在githab上搜索stetho,打开第一个facebook/stetho3.在Gradle Scri ...
- 【BZOJ2648】【kd_tree】SJY摆棋子
Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋 ...
- C#中foreach遍历学习笔记
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...
- 汇总前端最最常用的JS代码片段
html5选择器 //参数均接收一个合法的css选择器 element = document.querySelector('.foo,.bar');//返回带有foo或者bar样式类的首个元素 ele ...
- Ueditor之SAE移植
新浪SAE环境下使用UEditor http://www.cnblogs.com/zjzhome/p/3815460.html?utm_source=tuicool 在SAE上使用Ueditor的图片 ...
- Python核心编程2第六章课后练习
6-1 字符串 .string 模块中是否有一种字符串方法或者函数可以帮我鉴定一下一个字符串是否是另一个大字符串的一部分? #!/usr/bin/env python def contain(str1 ...
- [转] Java 8的新特性
简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和JVM等方面的十多个新特性.在本文中我们将学习这些新特性,并用实际的例子 ...
- BZOJ 1070 修车
Description 同一时刻有\(N\)位车主带着他们的爱车来到了汽车维修中心.维修中心共有\(M\)位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这\(M\)位技术 ...
- nodejs--book
https://github.com/0xlen/nodejs-wiki-book http://www.nodebeginner.org/index-zh-cn.html http://book.n ...