概要 本文对双向链表进行探讨,介绍的内容是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...中双向链表的使用思想 它是将双向链表节点嵌套在其它的结构体中;在遍历链表的时候,根据双链表节点的指针获取"它所在结构体的指针",从而再获取数据。
/******************** * 内核中链表的应用 ********************/ (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
大家好,又见面了,我是你们的朋友全栈君。 作为一个java初学者,最近遇到了回文链表结构这个难题,经过一番学习总算搞清楚个大概。 先来说一下什么是回文链表,会问链表在我们生活中经常能够遇到。...会问链表的结构就是 例如:1->2->3->2->1。我们将它反转过来还是与原链表相同,这种就称为回文结构。...具体方法:1.先找到链表的中间位置 2.然后将中间位置的链表反转 3.从两边向中间遍历 代码如图 class Node {...this.data = data; this.next = null; } } public class MyLinkedList { public Node head;//保存单链表的头节点的引用...//找出链表的中间位置 Node fast = this.head; Node slow = this.head; while(fast !
引言 链表的实现是基于结构体与指针两者实现的,常用的链表数据结构如下: //将int起别名ELEMTYPE,是为了方便修改链表中的数据域类型。...在Linux中设计了一种适合于各种类型数据域都可以使用的通用型链表: struct list_head { struct list_head *prev, *next; }; 摒弃掉数据域,只保留头尾指针...内核链表 链表的主要意义就是将分散地址的数据域通过指针排列成有序的队列。因此数据域是链表不可或缺的一部分,但是在实际使用中需要不同类型的数据域,因此也就限制了链表的通用。...Linux中在声明中抛弃了数据域,也就解决掉了这一问题。 原理 Linux使用链表的方法:使用时,自定义结构体包含数据域+链表结构体。...链表.png 如上图所示,将结构体A、B、C中的内核结构体指针构建成双链表,这样结构体A、B、C中的链表成员就可以互相索引了。
题目描述 难度级别:简单 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。...,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9....示例 2: 输入:head = [4,5,1,9], node = 1 输出:[4,5,9] 解释:给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9....提示: 链表至少包含两个节点。 链表中所有节点的值都是唯一的。 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 不要从你的函数中返回任何结果。...解题思路 题目中待传递给当前函数的实参node,它是链表中的某一个待删除的节点,然后从链表中删除这个节点。
容器 我们平时都经常遇到容器这个词,那么 Java 集合中的容器指的是什么呢?容器就是利用某种特定的数据结构来存储数据的。...物理结构就是数据在计算机中是怎么存储的,有数组和链表两种方式。数组是内存中一块连续的存储空间,所以可以随机访问(利用索引就可以访问)。链表是内存中离散的一些存储空间,所以必须要通过头节点来顺序访问。...容器中的元素个数(size) 方便定位到容器中最后一个元素的位置 时间复杂度 这里以 Java 集合中的 LinkedList 为例分析一下时间复杂度。...我们一般在链表的尾部插入一个新的节点不是需要一个循环遍历链表找到最后一个节点,然后修改相应引用的指向吗?那时间复杂度应该是 O(n) 呀。...确实是这样的,但是在 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:删除链表中的元素
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
class ListNode { public ListNode next; public Integer val; } /** * 只能删除连续的的重复数字...= null && pNode.val.equals(pHead.val)) { // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点...pNode = pNode.next; } return deleteDuplication(pNode); // 从第一个与当前结点不同的结点开始递归...deleteDuplication(pHead.next); // 保留当前结点,从下一个结点开始递归 return pHead; } } /** * 删除所有重复的节点
删除链表中等于给定值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) {} * }; 这是题目中给出的一个单向链表节点...除此之外还有双向链表(每一个链表有两条链,分别指向前一个和后一个节点),循环链表也是有的,就是收尾又链接起来,显而易见是有单向循环也有双向循环的。...链表的优点: 插入删除方便,只要改变指针的指向就可以,不用像数组一样需要移动数据。 链表的缺点: 因为内存不连续,所以查找效率不高。 它的优缺点和数组刚好是反过来的。
在上一小节中关于在链表中头部添加元素与在其他位置添加元素在逻辑上有所差别,这是由于我们在给链表添加元素时需要找到待添加元素位置的前一个元素所在的位置,但对于链表头来说,没有前置节点,因此在逻辑上就特殊一些...下面对代码进行改写: (1)将之前对头结点的定义改为对虚拟头结点的定义 将原来定义的头结点代码 private Node head; 改为 private Node dummyHead; (2)链表构造函数初始化时对虚拟节点进行初始化...//在链表的index(0--based)的位置添加新的元素e (实际不常用,练习用) public void add(int index, E e) { if (index...LinkedList() { 43 dummyHead = new Node(null, null); 44 size = 0; 45 } 46 47 //获取链表中的元素个数...isEmpty() { 54 return size == 0; 55 } 56 57 //在链表的index(0--based)的位置添加新的元素e (实际不常用
题意 给你链表的头节点 head 和一个整数 k 。 交换 链表正数第 k 个节点和倒数第 k 个节点的值后,返回链表的头节点(链表 从 1 开始索引)。 示例 示例 1: ?...k = 1 输出:[1] 示例 4: 输入:head = [1,2], k = 1 输出:[2,1] 示例 5: 输入:head = [1,2,3], k = 2 输出:[1,2,3] 提示 链表中节点的数目是...,找到第 k 个节点的上一个节点,然后将其 next 指向倒数第 k 个节点的,再将倒数第 k 个节点的 next 指向第 k 个节点的 next,然后将倒数第 k + 1 节点的 next 指向第 k...就是我把所以的 val 值取出来转数组,在 js 中,单纯的同类型数组,它在内存中是连续的,所以其访问复杂度是 O(1),所以我们把生成的数组的第(k - 1)个 和 数组的长度减去 k 的那位交换。...最后我们构造一个新的链表返回,当然啦,后面笔者比较菜用了两次遍历去构造这个链表然后返回。
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,返回链表头指针。...情况一 去掉重复部分保留一个 例如,链表1->2->3->3->4->4->5 处-理后为 1->2->3->4->5 代码: public ListNode deleteDuplication(ListNode...去掉重复部分,都不保留,有重复就去掉 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 思想: 主要用了一个指针preNotParall 每次指向上一个不重复的数据 headpre...是第一个不重复的数据(自己定义的,防止上来就是重复数据),也是头的上一个指针....pre和curr是工作指针,用来往后撸链表,留有用的. 看完代码的应该理解实际上我这里类似于用preNotParall来选取有用结点组成新链表.
01 题目信息 题目地址: https://leetcode-cn.com/problems/delete-node-in-a-linked-list/ 请编写一个函数,使其可以删除某个链表中给定的(非末尾...示例 1: 输入:head = [4,5,1,9], node = 5 输出:[4,1,9] 解释:给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9....提示: 链表至少包含两个节点。 链表中所有节点的值都是唯一的。 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 不要从你的函数中返回任何结果。...02 题解 作为合集中链表下的第一题,确实是较简单的只是一个单元操作,但如果不知道链表这种数据结构也还是是完成不了的。 链表是什么?...链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成,也就是包含值与模拟指针(引用)。大概如下: ?
前言 在一个排序的链表中,存在重复的节点,如何删除链表中重复的节点并返回删除后的链表头指针?例如:1->2->3->3->4->4->5,处理后为: 1->2->5。...本文将分享这个问题的解决思路与实现代码,欢迎各位感兴趣的开发者阅读本文。 常规思路 根据题意,我们可以知道链表中的元素是排好序的。如果节点重复的话,当前节点一定与下一个节点相同。...其次,我们需要创建两个指针: 一个指向当前不重复的节点,我们将它命名为pre 一个为搜索指针,用于搜索链表中与当前节点不重复的节点,我们将它命名为last 随后,我们为 pre 与 last 进行初始赋值...20220226224625702 实现代码 接下来,我们将上述思路转换为代码,如下所示: /** * 删除链表中的重复节点 * @param pHead 链表头节点 */ deleteDuplicatesNode...* * 删除链表中的重复节点(递归解法) * @param pHead 链表头节点 */ deleteDuplicatesNodeForRecursion(pHead: ListNode
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。...例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 解题思路 首先添加一个头节点,以方便碰到第一个,第二个节点就相同的情况 设置 first ,second 指针, first...指针指向当前确定不重复的那个节点,而second指针相当于工作指针,一直往后面搜索。
linux kernel中的list估计已经被各位前辈们写烂了,但是我还是想在这里记录一下; linux kernel里的很多数据结构都很经典, list链表就是其中之一 本篇要介绍的内容: list.../linux/types.h找到; 定义 实际上这就是一个双向循环链表, 且有一个头指针 list head的定义: struct list_head { struct list_head *next..., *prev; }; 这个定义中只有前向和后向指针,没任何的数据部分, 那我们基本上就知道了, 它不是被单独使用的,而是把它嵌入到用户定义的struct中, 将用户定义的数据结构串起来,作成list;...思想很巧妙, 对用户定义的数据结构侵入性很小, 实现了c++中std::List模板的功能; 虽然这个定义是叫head, 但其实嵌入到用户定义的数据结构中的也是这个....struct中,这个宏就是由这个list_head ptr来获取当前所处的struct对象的指针, 用了linux的经典宏定义 container_of #define list_entry(ptr,
刷了有关链表的一些算法题后,我发现其中用到快慢指针的题不少,像中间节点,倒数第n个节点以及链表成环 链表成环问题我只前发过两篇博客详细的讲了一下 跳转链接 https://blog.csdn.net...code=app_1562916241&uLinkId=usr1mkqgl919blen http://t.csdnimg.cn/e8p9P 今天就来说一下另外两道题 题目链接 leecode链表的中间节点...https://leetcode.cn/problems/middle-of-the-linked-list/description/ 牛客链表中倒数第k个节点 https://www.nowcoder.com...slow = slow->next; fast = fast->next; } } return slow; } 总结 关于这些问题,我们不难发现,在链表中快慢指针的应用相对频繁...,在后续对链表的学习和对有关链表的算法题进行公克的时候,不妨多往快慢指针方面去想想
Source Code Pro Source Code Pro 步入正题,讲讲链表的操作 节点 首先得有一个节点类,用于存储数据 <?...(用于操作节点数据) 操作类的代码由于太长,我们分部分解析 头插入(因为比较简单,所以先讲这个) 听名字,就知道是从头部插入一个节点 当链表为空,则初始化当前节点 当链表不为空,把新节点作为头结点 public...// 1 2 5 8 9 $manager->insertEnd(9); // 3 $manager->find(8); // 1 2 8 9 $manager->delete(2); 查找 查找链表的值也是很简单的...,只要遍历即可 /** * 查找链表的值中的索引 * 成功返回索引值,找不到返回 -1 * * @param int $data * @return int */ public function find...,找到相等的值,找到返回索引值,找不到返回 -1 删除 /** * 删除链表的节点 * * @param int $index * @return bool */ public function
领取专属 10元无门槛券
手把手带您无忧上云