6. LinkedList与链表
一、ArrayList的缺陷
通过源码知道,ArrayList底层使用数组来存储元素,由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。所以,java集合中又引入了LinkedList,即链表结构。
二、链表
1. 链表的概念及结构
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
1.1 单向或者双向
1.2 带头或者不带头
1.3 循环或者非循环
重点掌握两种:
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
- 无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。
2. 链表的实现
import java.util.List;public class MySingleLinkedList {static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;//代表链表的头节点public void createList() {ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(23);ListNode node3 = new ListNode(34);ListNode node4 = new ListNode(45);ListNode node5 = new ListNode(56);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node5;this.head = node1;}public void display() {ListNode cur = head;while (cur != null) {System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}/*** 从指定位置 newHead 开始打印链表* @param newHead*/public void display(ListNode newHead) {ListNode cur = newHead;while (cur != null) {System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}public int size(){int count = 0;ListNode cur = head;while (cur != null) {count++;cur = cur.next;}return count;}public void addFirst(int val) {ListNode node = new ListNode(val);node.next = head;head = node;}public void addLast(int val) {ListNode node = new ListNode(val);if(head == null) {head = node;return;}ListNode cur = head;while (cur.next != null) {cur = cur.next;}cur.next = node;}public void addIndex(int index,int val) {//1.判断index的合法性try {checkIndex(index);}catch (IndexNotLegalException e) {e.printStackTrace();}//2.index == 0 || index == size()if(index == 0) {addFirst(val);return;}if(index == size()) {addLast(val);return;}//3. 找到index的前一个位置ListNode cur = findIndexSubOne(index);//4. 进行连接ListNode node = new ListNode(val);node.next = cur.next;cur.next = node;}private ListNode findIndexSubOne(int index) {int count = 0;ListNode cur = head;while (count != index-1) {cur = cur.next;count++;}return cur;}private void checkIndex(int index) throws IndexNotLegalException{if(index < 0 || index > size()) {throw new IndexNotLegalException("index不合法");}}public boolean contains(int val) {ListNode cur = head;while (cur != null) {if(cur.val == val) {return true;}cur = cur.next;}return false;}public void remove(int val) {if(head == null) {return;}if(head.val == val) {head = head.next;return;}ListNode cur = head;while (cur.next != null) {if(cur.next.val == val) {ListNode del = cur.next;cur.next = del.next;return;}cur = cur.next;}}public void removeAllKey(int val) {//1. 判空if(this.head == null) {return;}//2. 定义prev 和 curListNode prev = head;ListNode cur = head.next;//3.开始判断并且删除while(cur != null) {if(cur.val == val) {prev.next = cur.next;//cur = cur.next;}else {prev = cur;//prev = prev.next;//cur = cur.next;}cur = cur.next;}//4.处理头节点if(head.val == val) {head = head.next;}}public void clear() {//head = null;ListNode cur = head;while (cur != null) {ListNode curN = cur.next;//cur.val = null;cur.next = null;cur = curN;}head = null;}
}
三、链表面试题
1. 删除链表中等于给定值 val 的所有节点。
2. 反转一个单链表。
3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
4. 输入一个链表,返回该链表中倒数第k个结点。
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前。
7. 链表的回文结构。
8. 输入两个链表,找出它们的第一个公共结点。
9. 给定一个链表,判断链表中是否有环。
10. 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL。
四、LinkedList的模拟实现
public class MyLinkedList {static class ListNode {public int val;public ListNode prev;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;public ListNode last;//头插法public void addFirst(int data){ListNode node = new ListNode(data);if(head == null) {head = node;last = node;//return;}else {node.next = head;head.prev = node;head = node;}}//尾插法public void addLast(int data){ListNode node = new ListNode(data);if(head == null) {head = last = node;}else {last.next = node;node.prev = last;last = node;}}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data){if(index < 0 || index > size()) {return;}if(index == 0) {addFirst(data);return;}if(index == size()) {addLast(data);return;}ListNode cur = searchIndex(index);ListNode node = new ListNode(data);node.next = cur;cur.prev.next = node;node.prev = cur.prev;cur.prev = node;}private ListNode searchIndex(int index) {ListNode cur = head;int count = 0;while (count != index) {cur = cur.next;count++;}return cur;}//查找是否包含关键字key是否在单链表当中public boolean contains(int key){ListNode cur = head;while (cur != null) {if(cur.val == key) {return true;}cur =cur.next;}return false;}//得到单链表的长度public int size(){int count = 0;ListNode cur = head;while (cur != null) {count++;cur =cur.next;}return count;}public void display(){ListNode cur = head;while (cur != null) {System.out.print(cur.val+" ");cur =cur.next;}System.out.println();}//删除第一次出现关键字为key的节点public void remove(int key){ListNode cur = head;while (cur != null) {if(cur.val == key) {if(cur == head) {head = head.next;//判断 头节点是不是1个if(head != null) {head.prev = null;}else {last = null;}}else {cur.prev.next = cur.next;if(cur.next == null) {//cur.prev.next = cur.next;last = cur.prev;}else {//cur.prev.next = cur.next;cur.next.prev = cur.prev;}}return;}else {cur = cur.next;}}}//删除所有值为key的节点public void removeAllKey(int key){ListNode cur = head;while (cur != null) {if(cur.val == key) {if(cur == head) {head = head.next;//判断 头节点是不是1个if(head != null) {head.prev = null;}else {last = null;}}else {cur.prev.next = cur.next;if(cur.next == null) {//cur.prev.next = cur.next;last = cur.prev;}else {//cur.prev.next = cur.next;cur.next.prev = cur.prev;}}}cur = cur.next;}}public void clear(){ListNode cur = head;while (cur != null) {ListNode curN = cur.next;cur.next = null;cur.prev = null;cur = curN;}head = null;last = null;}}
五、LinkedList的使用
1. 什么是LinkedList
LinkedList的底层是双向链表结构(链表后面介绍),由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在集合框架中,LinkedList也实现了List接口,具体如下:
【说明】
- LinkedList实现了List接口
- LinkedList的底层使用了双向链表
- LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
- LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
- LinkedList比较适合任意位置插入的场景
2. LinkedList的使用
2.1 LinkedList的构造
public static void main(String[] args) {// 构造一个空的LinkedListList<Integer> list1 = new LinkedList<>();List<String> list2 = new java.util.ArrayList<>();list2.add("JavaSE");list2.add("JavaWeb");list2.add("JavaEE");// 使用ArrayList构造LinkedListList<String> list3 = new LinkedList<>(list2);
}
2.2 LinkedList的其他常用方法介绍
2.3 LinkedList的遍历
public class Test {public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);list.add(6);list.add(7);list.add(8);System.out.println(list.size());//foreach遍历for (int e:list) {System.out.print(e + ", "); // 1, 2, 3, 4, 5, 6, 7, 8, }System.out.println();//使用迭代器遍历——正向遍历ListIterator<Integer> it = list.listIterator();while (it.hasNext()){System.out.print(it.next() + ", "); // 1, 2, 3, 4, 5, 6, 7, 8, }System.out.println();//使用反向迭代器——反向遍历ListIterator<Integer> rit = list.listIterator(list.size());while (rit.hasPrevious()){System.out.print(rit.previous() + ", "); // 8, 7, 6, 5, 4, 3, 2, 1, }System.out.println();}
}
六、ArrayList和LinkedList的区别
相关文章:

6. LinkedList与链表
一、ArrayList的缺陷 通过源码知道,ArrayList底层使用数组来存储元素,由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比…...

Statcounter Global Stats 提供全球统计数据信息
Statcounter Global Stats 提供全球统计数据信息 1. Statcounter Global Stats2. Mobile & Tablet Android Version Market Share WorldwideReferences Statcounter Global Stats https://gs.statcounter.com/ Statcounter Global Stats are brought to you by Statcounte…...
Linux kernel中的dts dtsi dtb dtc dtb.img dtbo.img
1、问题 kernel与hsm会设置一些gpio,但是某些gpio会在kernel与hsm侧共同设置,导致最终的设置结果失败,将kernel侧在dts文件中设置的gpio注释掉之后,发现hsm设置gpio时还是失败 2、问题原因 因为dts文件不仅仅会影响kernel镜像&…...

微信小程序页面制作——个人信息
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
使用C++11的`std::async`执行异步任务:实战指南
使用C11的std::async执行异步任务:实战指南 在现代软件开发中,异步编程是提高应用程序性能和响应速度的重要手段。C11引入了std::async,使得编写异步任务变得更加简单和直观。本文将详细介绍如何使用std::async执行异步任务,并提…...

【高阶数据结构】B树、B+树、B*树
B树、B树、B*树 1. 常见的搜索结构2. B树概念3. B树的插入分析4. B树的插入实现4.1 B树的节点设计4.2 B树的部分插入实现14.3 B树的查找4.4 B树的部分插入实现24.5 插入key的过程4.7 B树的插入完整代码4.8 B树的简单验证4.9 B树的删除4.10 B树的性能分析 5. B树6. B*树7. 总结8…...

HBuilderx中vue页面引用scss样式
scss为css样式的预编译器,引入了变量、嵌入、混合、集成、引入等功能,相对于css样式,实现了样式的编程,具有更灵活的样式编写模式。 那么在HBuilderx中,“.vue”格式页面如何调用scss样式呢?详细如下&#…...

粒子群算法原理的示例介绍
一:粒子群优化算法的介绍 粒子群优化算法(PSO)是一种基于群体智能的优化算法,于1995年提出。它受到鸟群狩猎行为的启发,通过模拟鸟群或鱼群的社会行为来进行问题的求解。 基本原理 粒子群算法中,每个解决…...
GNU/Linux - Open函数使用的O_CLOEXEC flag
在 Linux 中,“O_CLOEXEC ”标志与 “open ”系统调用一起使用,用于指定在使用 “exec ”系列函数(如 “execve”、“execl ”等)执行新程序时,“open ”返回的文件描述符应自动关闭。 In Linux, the O_CLOEXEC flag i…...

AWQ量化(Activation-aware Weight Quantization)
论文: AWQ: Activation-aware Weight Quantization for On-Device LLM Compression and Acceleration 中文解读: 深入理解AWQ量化技术 - 知乎 (zhihu.com) 动机:端侧设备用LLM,为了减少显存占用量,所以要用INT4量化&am…...

SprinBoot+Vue体育商品推荐的设计与实现
目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…...

【Python基础】Python函数
本文收录于 《Python编程入门》专栏,从零基础开始,分享一些Python编程基础知识,欢迎关注,谢谢! 文章目录 一、前言二、函数的定义与调用三、函数参数3.1 位置参数3.2 默认参数3.3 可变数量参数(或不定长参数…...

【超简单】1分钟解决ppt全文字体一键设置
省流 ppt的全部字体需要在“幻灯片母版”里面,“自定义字体”去设置好标题与正文的字体之后才算全部设置完毕 “视图”---“幻灯片母版” 找到“字体”---“自定义字体” 设置好中文和西文的字体,都可以按照自己的选择来,保存即可 吐槽 之…...

数组与贪心算法——179、56、57、228(2简2中)
179. 最大数(简单) 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。 注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。 解法一、自定义比较…...

WireShark过滤器
文章目录 一、WireShark过滤器概念1. 捕获过滤器(Capture Filters)2. 显示过滤器(Display Filters)3. 捕获过滤器与显示过滤器的区别4. 过滤器语法结构实际应用场景 二、WireShark捕获数据包列表1. **No.(序号…...

2024年全新deepfacelive如何对应使用直播伴侣-腾讯会议等第三方软件
# 2024年全新deepfacelive如何对应使用直播伴侣-腾讯会议等第三方软件 前提按照之前的步骤打开deepfacelive正确配置并且在窗口已经输出了换脸后的视频,不懂步骤可以移步 https://doc.youyacao.com/88/2225 ## 首先下载obs并配置 https://obsproject.com/ 通过…...
告别懵逼——前端项目调试与问题排查方法小结
在日常工作中,我们常常会遇到以下两类典型的挑战: 场景一: 接手无文档的老项目 1、情景描述: 你接手了一个历史久远的项目,项目文档缺失,前任开发者已经离开,而你对当前的业务逻辑和代码结构都…...

[数据集][目标检测]肺炎检测数据集VOC+YOLO格式4983张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4983 标注数量(xml文件个数):4983 标注数量(txt文件个数):4983 标注…...

顶层const和底层const
在C中,const修饰符用于声明常量,有两种常见的形式:顶层const和底层const,它们之间的区别在于它们修饰的对象及其在不同场景中的作用。 1. 顶层const (Top-level const) 顶层const用于修饰变量本身,使其成为常量。这意…...

嵌入式Openharmony系统构建与启动详解
大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建 首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...