linux kernel中的list估计已经被各位前辈们写烂了,但是我还是想在这里记录一下; linux kernel里的很多数据结构都很经典, list链表就是其中之一 本篇要介绍的内容: list...的定义 list提供的操作方法 注意事项 使用实例 ---- List 所在文件: List的所有操作可以在 include/linux/list.h找到; List head的定义可以在 include.../linux/types.h找到; 定义 实际上这就是一个双向循环链表, 且有一个头指针 list head的定义: struct list_head { struct list_head *next...new, struct list_head *head) { __list_add(new, head, head->next); } 在尾部插入,在最后一个元素间和头指针间插入, 因为是循环链表嘛...head); } list_entry宏 按之前说的, 这个list_head都有要嵌入到用户定义的struct中,这个宏就是由这个list_head ptr来获取当前所处的struct对象的指针, 用了linux
*p) { wait->next = wait; *p = wait; } else { /* 在第一个节点后面插入节点,形成单向循环链表 thanks to...传统的头插法只能形成单链表,不能循环,因为循环需要拿尾指针的next指向第一个 节点,但是随着链表的变成,无法找到尾节点。...wait->next = wait; *p = wait; } else { // 头插法,形成单向链表...(ok = 1) && #endif ((*p = wait->next) == wait)) { *p = NULL; } else { // 从自己开始遍历单向循环链表
链表相关数据结构 在 Redis 的源码中,链表的数据结构和相关的操作都包含在 adlist.h 和 adlist.c 两个文件当中,这两个文件是 Redis 中对底层链表的所有实现。...在 adlist.h 文件中,有两个关于链表的重要数据结构,一个是双向链表的数据结构,另外一个是用于管理双向链表的数据结构。...无环链表 Redis 的链表是无环的双向链表,这点可以通过 Redis 插入头节点和插入尾节点的函数看出,两个函数代码如下: /** * 将值插入到链表的头部 */ list *listAddNodeHead...迭代器 链表节点的复制、搜索都会涉及到链表的遍历,链表的遍历使用了迭代器的数据结构。...喝水不忘打井人,没有黄老师的书籍做我 Redis 学习的指路明灯,恐怕对于学习 Redis 的源码我会艰难万分。再次感谢黄老师写的关于 Redis 的书籍,能够让好的技术遍地开花。
引言 链表的实现是基于结构体与指针两者实现的,常用的链表数据结构如下: //将int起别名ELEMTYPE,是为了方便修改链表中的数据域类型。...在Linux中设计了一种适合于各种类型数据域都可以使用的通用型链表: struct list_head { struct list_head *prev, *next; }; 摒弃掉数据域,只保留头尾指针...Linux中在声明中抛弃了数据域,也就解决掉了这一问题。 原理 Linux使用链表的方法:使用时,自定义结构体包含数据域+链表结构体。...即让内部链表成员与其他链表成员构建成双链表,实现遍历寻址,然后通过链表成员找到包含该成员的结构体首地址。 ?...「linux实现获取结构体首地址:」 #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&(
相对于之前介绍的字典和SDS字符串库,Redis的双向链表库则是非常标准的、教科书般简单的库。但是作为Redis源码的一部分,我决定还是要讲一讲的。...在《Redis源码解析——字典结构》一文中,我们看到用户创建字典时需要传入的dictType结构体,就是一个承载数据的上述处理方法的载体。...还可以让这个迭代器指向另外一个链表,而非创建它时指向的链表。... 链表的复制过程就是通过一个从头向尾访问的迭代器,将原链表中的数据复制到新建的链表中。...它将链表最后一个节点移动到链表头部。我想设计这么一个方法是为了让链表内容可以在无状态记录的情况下被均匀的轮询到。
链表在Redis中的应用场景 1.列表键的底层实现之一 2.RedisServer中保存的客户端状态信息 3.发布与订阅 4.慢查询 5.监视器 链表节点数据结构 Redis实现的是双端无环链表...节点值 } 链表结构 通过list结构持有链表,其中head、tail属性分别指向表头和表尾节点,length属性用于记录链表长度,从而可以使获取链表长度的复杂度从O(N)降低为O(1)...//持有链表结构 type list struct { //指向表头节点 head *listNode //指向表尾节点 tail *listNode //记录链表长度 length...(iter) return node } 7.链表给定索引节点的值 PS:源码中并没有用到迭代器,重写使用了迭代器 //返回链表给定索引上的值 func (l *list) Index(index...如果节点复制函数dup为nil则直接复制节点值 //复制链表 func (l *list)Dup() (*list) { //源链表为空直接返回 if nil == l { return nil
**链表是通过逻辑储存的方式通过节点的引用来获取元素值,每个节点包含两个部分 首先第一部分是value元素值。...链表的复杂度相对有序数组要方便他的时间复杂度分别是O(1)和O(N)。...** 创建一个ILindkedList接口创建方法(模拟实现链表方法) import java.util.List; public interface ILinkedList {...addLast(int data); //在指定位置新增元素 public void addIndex(int index,int data); //在链表中删除...public int size(); //清空链表 void clean(); //反转链表元素 public MyLinkedList.NodeList
先看一下源码里面官方的介绍: ?...image.png 这段话大体意思是说,ziplist是一种特殊编码的双链表,主要是为了节省内存而存在的,整个都是由字符串和整数值组成的,其中整数值被编码为实际的整数,而不是一系列字符。...image.png 与其他的数据结构不同并没有定义专门的数据结构来保存ziplist的信息,而是采用了一组宏来定位每个成员的地址,具体源码的话可以看一src/ziplist.c ?
/******************** * 内核中链表的应用 ********************/ (1)介绍 在Linux内核中使用了大量的链表结构来组织数据,包括设备列表以及各种功能模块中的数据组织...这些链表大多采用在include/linux/list.h实现的一个相当精彩的链表数据结构。...和以前介绍的双链表结构模型不同,这里的list_head没有数据域。在Linux内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。...如: struct my_struct{ struct list_head list; unsigned long dog; void *cat; }; linux中的链表没有固定的表头,从任何元素开始访问都可以...定义在linux/list.h> a.增加节点 list_add(struct list_head *new, struct list_head *head); 向指定链表的head
想起前段时间, 看到FreeRTOS提供的链表处理方式(《 FreeRTOS 任务调度 List 组织 》), 将链表结构定义和实际使用时具体节点数据内容分开定义, 供系统各个模块使用。...查看linux的源码, 发现linux中也为我们提供了相似的实现(源码), 把一些共性统一起来。 类是 python 中for_each处理,有些意思。...linux 下的链表定义在文件 include/linux/types.h, 采用的是双向列表 struct list_head { struct list_head *next, *prev;...list 利用这个定义, 我定义了一个自己的list数据结构, 并copy了一些接口实现,感受下,linux 是如何管理链表的。...int_node, list); printf("%d ", pnode->val); } printf("\n"); return 0; } 虽然比较简单,记录下,学习linux
链表的实现比较简单,有几个模块使用了这个功能,定时器就是其中一个。 'use strict'; function init(list) { list.
分析代码之前先看看链表的数据结构。...1 新建一个链表 // 新建一个链表头结点 list *listCreate(void) { struct list *list; if ((list = zmalloc(sizeof...(*list))) == NULL) return NULL; // 空链表,还没有节点 list->head = list->tail = NULL; // 链表中的节点数...释放节点value域的函数 list->free = NULL; // 匹配节点的函数 list->match = NULL; return list; } 2 释放一个链表...// 释放一个链表 void listRelease(list *list) { unsigned int len; listNode *current, *next; //
本质上这种列表可以使用数组、链表作为其底层结构,不知道Python中的列表是以什么作为底层结构的。...但是redis的列表既不是用链表,也不是用数组作为其底层实现的,原因也显而易见:数组不方便,弄个二维的?柔性的?怎么写?链表可以实现,通用链表嘛,数据域放 void* 就可以实现列表功能。...但是,链表的缺点也很明显,容易造成内存碎片。 在这个大环境下,秉承着“能省就省”的指导思想,请你设计一款数据结构。...鉴于这里真心不是链表,是列表。 所以,按数组那一套来。对。 很麻烦吧。其实不麻烦,你在redis里见过它给你中间插入的机会了吗?更不要说头插了,你见过它给你头插的机会了吗?...插个题外话:大数据插入时,数组不一定输给链表。在尾插的时候,数组的优势是远超链表的(当然,仅限于尾插)。在我两个月前的博客里有做过这一系列的实验。
文章目录 一、下载 Linux 内核源码 二、使用 VSCode 阅读 Linux 内核源码 一、下载 Linux 内核源码 ---- 参考 【Linux 内核】编译 Linux 内核 ① ( 下载指定版本的...Linux 内核源码 | Linux 内核版本号含义 | 主版本号 | 次版本号 | 小版本号 | 稳定版本 ) 博客 , 下载 Linux 5.6.18 版本的内核源码 ; 5.x 内核源码下载地址.../pub/linux/kernel/v5.x/linux-5.6.18.tar.gz 下载完 Linux 源码后 , 如果在 Windows 系统中解压 , 需要使用管理员权限在 命令行终端 中解压 ,...Code ) 博客 , 安装 VSCode 软件 ; 打开 VSCode , 选择 ” 菜单栏 / 文件 / 打开文件夹 ” 选项 , 选择 Linux 内核源码目录 , 点击 ” 选择文件夹 ”...按钮 , 此时就可以在 VSCode 中阅读 Linux 内核源码 ; 发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163620.html原文链接:https
文章目录 一、下载 Linux 内核源码 二、使用 VSCode 阅读 Linux 内核源码 一、下载 Linux 内核源码 ---- 参考 【Linux 内核】编译 Linux 内核 ① ( 下载指定版本的...Linux 内核源码 | Linux 内核版本号含义 | 主版本号 | 次版本号 | 小版本号 | 稳定版本 ) 博客 , 下载 Linux 5.6.18 版本的内核源码 ; 5.x 内核源码下载地址.../pub/linux/kernel/v5.x/linux-5.6.18.tar.gz 下载完 Linux 源码后 , 如果在 Windows 系统中解压 , 需要使用管理员权限在 命令行终端 中解压 ,...Code ) 博客 , 安装 VSCode 软件 ; 打开 VSCode , 选择 " 菜单栏 / 文件 / 打开文件夹 " 选项 , 选择 Linux 内核源码目录 , 点击 " 选择文件夹 "...按钮 , 此时就可以在 VSCode 中阅读 Linux 内核源码 ;
printf("num = %d, math = %d\n", temp->num, temp->math); } printf("\n"); return 0; } 运行效果: 内核双链表效果图...其实关于内核中链表的操作还有很多的函数,目前就分析这几个。其余留给自己尝试。
单链表在插入和删除不需要移动元素,只需改变指针的指向即可。 单链表 概念:单链表是在物理存储结构上不连续,逻辑结构上连续的线性表。...打印单链表时应注意: 循环体,单链表的循环通过next指针来实现,结束条件是最后一个节点的next指针为空。...,二是有节点,传递的不是空链表。...当链表为空时,这不就是头插吗?!...源码 SListNode.h #pragma once #include #include #include typedef int
链表 链表是一种离散存储结构,其在内存中存储不是连续的,每个数据元素都通过一个指针指向其下一个元素的地址。根据指针域的不同,链表又分为单链表、双向链表、循环链表等。...对于单链表而言,可以得出以下几个结论: 声明一个链表时,不需要知道其长度,也不需要连续的内存块,所以其大小可以动态调整。...增加与删除一个元素更方便了,因为没有对内存地址的限制,我们只需要在对应节点合理处理下指针域的值,就可以把一个元素插入链表或者从链表删除。...数组与链表的选择 通过以上分析,数组和链表对我们影响最大的几点区别在于: 数组按位置查找迅速,链表增删方便 数组是固定大小,链表可以随时扩充与缩减 链表每个元素占据内存略多于数组 数组和链表在查询方面表现都比较一般...设计良好的哈希表,能同时兼备数组和链表的优点,它能在插入和查找时都具备良好的性能。然而设计不好的哈希表,有可能会出现较多的哈希碰撞,导致链表过长,从而哈希表会更像一个链表。
数据结构之双向链表(源码) 线性表 双向链表是线性表链式存储结构的一种,若对链式存储结构进行分类可以分为八种。...循环、不循环:链表的循环结构是将不循环链表的尾节点从指向空指针改为指向头指针。完成链表的自循环。...本篇所述:带头双向循环链表,简称双链表,双链表和单链表(不带头单向不循环链表)是八种链表中常用的两个链表, 双向链表 双链表结构 双链表是一个带头双向循环链表,更据它的特性不能想出,在一个双链表的一个节点里它的指针域用来存放前一个节点的地址和存放下一个节点的地址...,就是只有一个头节点,这时双链表被看作是空链表,这与前文实现的单链表不同,单链表是需要将所有节点删除才为空,因为它没有头节点,这才将所有节点删除。...源码 List.h #pragma once #include #include #include #include <stdbool.h
简介 链表是Linux 内核中最简单,最普通的数据结构。...链表是一种存放和操作可变数量元素(常称为节点) 的数据结构,链表和静态数组的不同之处在于,它所包含的元素都是动态创建并插入链表的,在编译 时不必知道具体需要创建多少个元素,另外也因为链表中每个元素的创建时间各不相同...根据它的特性,链表可分为:单链表,双链表,单向循环链表和双向循环链表,今天总结记录的就是 最简单的单链表, 1.1 节点类型描述 1 typedef struct node_t { ...,我们如何表现空链表呢?...链表基本运算的相关"算法"操作 or 操刀(~烹羊宰牛且为乐,会须一饮三百杯~) 链表的运算除了上面的创建空链表,还有数据的插入,删除,查找等函数,链表的运算有各种实现方 法,如何写出一个高效的
领取专属 10元无门槛券
手把手带您无忧上云