概要 本文对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of。...内容包括: 1.Linux中的两个经典宏定义 2.Linux中双向链表的经典实现 Linux中的两个经典宏定义 倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of...在linux内核的include/linux/kernel.h中定义。...Linux中双向链表的经典实现 1.Linux中双向链表介绍 Linux双向链表的定义主要涉及到两个文件: include/linux/types.h include/linux/list.h Linux...3.Linux中双向链表的使用示例 双向链表代码(list.h): 1 #ifndef _LIST_HEAD_H 2 #define _LIST_HEAD_H 3 // 双向链表节点 4 struct
引言 链表的实现是基于结构体与指针两者实现的,常用的链表数据结构如下: //将int起别名ELEMTYPE,是为了方便修改链表中的数据域类型。...在Linux中设计了一种适合于各种类型数据域都可以使用的通用型链表: struct list_head { struct list_head *prev, *next; }; 摒弃掉数据域,只保留头尾指针...内核链表 链表的主要意义就是将分散地址的数据域通过指针排列成有序的队列。因此数据域是链表不可或缺的一部分,但是在实际使用中需要不同类型的数据域,因此也就限制了链表的通用。...Linux中在声明中抛弃了数据域,也就解决掉了这一问题。 原理 Linux使用链表的方法:使用时,自定义结构体包含数据域+链表结构体。...链表.png 如上图所示,将结构体A、B、C中的内核结构体指针构建成双链表,这样结构体A、B、C中的链表成员就可以互相索引了。
作为一个java初学者,最近遇到了回文链表结构这个难题,经过一番学习总算搞清楚个大概。 先来说一下什么是回文链表,会问链表在我们生活中经常能够遇到。...会问链表的结构就是 例如:1->2->3->2->1。我们将它反转过来还是与原链表相同,这种就称为回文结构。...具体方法:1.先找到链表的中间位置 2.然后将中间位置的链表反转 3.从两边向中间遍历 代码如图 class Node {...if(this.head == null) { return false; } //判断头节点的next是否为空,如果为空,证明只有一个链表...,就是回文链表 if(this.head.next == null) { return true; } //找出链表的中间位置
/******************** * 内核中链表的应用 ********************/ (1)介绍 在Linux内核中使用了大量的链表结构来组织数据,包括设备列表以及各种功能模块中的数据组织...这些链表大多采用在include/linux/list.h实现的一个相当精彩的链表数据结构。...和以前介绍的双链表结构模型不同,这里的list_head没有数据域。在Linux内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。...如: struct my_struct{ struct list_head list; unsigned long dog; void *cat; }; linux中的链表没有固定的表头,从任何元素开始访问都可以...定义在 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 是如何管理链表的。...另外一种做法是定义list_head中, 包含一个成员变量,指向其所属,FreeRTOS是如此做的。
1.链表中头节点的引入 1.1基本的链表结构: ? 1.2对于链表来说,若想访问链表中每个节点则需要把链表的头存起来,假如链表的头节点为head,指向链表中第一个节点,如图: ?...LinkedList() { head = null; size = 0; } //获取链表中的元素个数 public int getSize...从上不难看出,对于在链表中添加元素关键是找到要添加的节点的前一个节点,因此对于在索引为0的节点添加元素就需要单独处理。...LinkedList; 2 3 public class LinkedList { 4 //将Node节点设计成私有的类中类 5 private class Node<...无参数构造函数 42 public LinkedList() { 43 head = null; 44 size = 0; 45 } 46 47 //获取链表中的元素个数
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..., *prev; }; 这个定义中只有前向和后向指针,没任何的数据部分, 那我们基本上就知道了, 它不是被单独使用的,而是把它嵌入到用户定义的struct中, 将用户定义的数据结构串起来,作成list;...思想很巧妙, 对用户定义的数据结构侵入性很小, 实现了c++中std::List模板的功能; 虽然这个定义是叫head, 但其实嵌入到用户定义的数据结构中的也是这个.
package linklist; public class Node { public int iData; public double dData; ...
算法: 核心点在于如何找到重复节点,有序链表的话,只要下一个节点与当前节点数值一样就是重复节点,直接将当前节点指向下一个节点的下一个节点即可。 本算法需要注意哨兵节点的小技巧。...题目1:删除排序链表中的重复元素 https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/submissions/ ?...题目2: 删除排序链表中的重复元素 ?
描述 在linux内核中封装了一个通用的双向链表库,这个通用的链表库有很好的扩展性和封装性,它给我们提供了一个固定的指针域结构体,我们在使用的时候,只需要在我们定义的数据域结构体中包含这个指针域结构体就可以了...传统的链表结构 struct node{ int key; int val; node* prev; node* next; } linux 内核通用链表库结构 提供给我们的指针域结构体...内核中是一个常用的宏,用于从包含在某个 //结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变 //量中某个成员的首地址进而获得整个结构体变量的首地址 #define container_of(ptr...list_add-先入先出模式 我们的链表节点,实际在内存中的展示形态 ?...内核提供的这个通用链表库里面还有很多其他的接口,这里没有详细的一一举例,有兴趣的可以自己去看看,在源码包 include/linux/list.h 文件里面,不过通过阅读一些源代码确实对我们也有很大的提高
printf("num = %d, math = %d\n", temp->num, temp->math); } printf("\n"); return 0; } 运行效果: 内核双链表效果图...其实关于内核中链表的操作还有很多的函数,目前就分析这几个。其余留给自己尝试。
ListNode* l = new ListNode(0); input(l); Solution s; s.deleteNode(l->next->next);//输入1 2 3 ,链表中存储...3 2 1 ,递归逆序输出:1 2 3 ,删除2 cout << "链表打印:" << endl; display(l->next); cout << endl; } int main
Reverse Linked List 反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表。...然后我们需要将head设置为反向列表中的最后一个节点。 我们只需将其下一个节点设置在原始列表中(head-> next)指向它,并将其下一个设置为NULL。...Reverse Linked List II 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。 说明: 1 ≤ m ≤ n ≤ 链表长度。
在上一小节中关于在链表中头部添加元素与在其他位置添加元素在逻辑上有所差别,这是由于我们在给链表添加元素时需要找到待添加元素位置的前一个元素所在的位置,但对于链表头来说,没有前置节点,因此在逻辑上就特殊一些...(空链表时存在一个唯一的虚拟头结点) //无参数构造函数 public LinkedList() { dummyHead = new Node(null, null);...size = 0; } (3)改进之前的add(int index,E e)方法,之前对在头结点添加元素单独做了处理(if-else判断),如下: 1 //在链表的index(0--based...} 改进后的完整代码为: 1 package LinkedList; 2 3 public class LinkedList { 4 //将Node节点设计成私有的类中类...LinkedList() { 43 dummyHead = new Node(null, null); 44 size = 0; 45 } 46 47 //获取链表中的元素个数
题目描述 难度级别:简单 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。...现有一个链表 -- head = [4,5,1,9],它可以表示为: 示例 1: 输入:head = [4,5,1,9], node = 5 输出:[4,1,9] 解释:给定你链表中值为 5 的第二个节点...,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9....提示: 链表至少包含两个节点。 链表中所有节点的值都是唯一的。 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 不要从你的函数中返回任何结果。...解题思路 题目中待传递给当前函数的实参node,它是链表中的某一个待删除的节点,然后从链表中删除这个节点。
删除链表中等于给定值val的所有节点。 样例 给出链表 1->2->3->3->4->5->3, 和 val = 3, 你需要返回删除3之后的链表:1->2->4->5。 基本操作。...链表 链表有很多种,这里给的是单向链表,链表由节点构成,每一个节点包含两个信息,分别是数据和链(实际上就是一个指针,指向下一个节点,如果没有下一个这个指针为NULL)。...int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; 这是题目中给出的一个单向链表节点...除此之外还有双向链表(每一个链表有两条链,分别指向前一个和后一个节点),循环链表也是有的,就是收尾又链接起来,显而易见是有单向循环也有双向循环的。...链表的优点: 插入删除方便,只要改变指针的指向就可以,不用像数组一样需要移动数据。 链表的缺点: 因为内存不连续,所以查找效率不高。 它的优缺点和数组刚好是反过来的。
容器 我们平时都经常遇到容器这个词,那么 Java 集合中的容器指的是什么呢?容器就是利用某种特定的数据结构来存储数据的。...物理结构就是数据在计算机中是怎么存储的,有数组和链表两种方式。数组是内存中一块连续的存储空间,所以可以随机访问(利用索引就可以访问)。链表是内存中离散的一些存储空间,所以必须要通过头节点来顺序访问。...当 hash 表中的元素达到某个数量时,随着元素的增多,冲突也越来越多,性能就会下降。...容器中的元素个数(size) 方便定位到容器中最后一个元素的位置 时间复杂度 这里以 Java 集合中的 LinkedList 为例分析一下时间复杂度。...确实是这样的,但是在 Java 的 LinkedList 中它利用了一个尾指针(引用) 记录了链表最后一个节点的位置,不需要再去遍历链表,所以时间复杂度为 O(1)。
题意 删除链表中等于给定值 val 的所有节点。 样例 给出链表 1->2->3->3->4->5->3, 和 val = 3, 你需要返回删除3之后的链表:1->2->4->5。...思路 只需要将一个指针,遍历链表,当链表中有元素与 val 值相同时,让当前节点的 next 节点直接指向 当前节点的 next.next 节点即可。...head.next; } } return dummy.next; } } 原题地址 LintCode:删除链表中的元素
*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 { // 从自己开始遍历单向循环链表
领取专属 10元无门槛券
手把手带您无忧上云