数据结构之链表(LinkedList详解)

article/2025/9/11 1:07:36

 

文章目录

  • 一、什么是LinkedList?
  • 二、LinkedList的使用
  • 三、LinkedList自实现
  • 四、链表实现逆序打印的两种方式(递归和非递归)
  • 五、ArrayList和LinkedList有什么区别?

一、什么是LinkedList?

LinkedList的底层是 双向链表结构(链表后面介绍),由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在集合框架中,LinkedList也实现了List接口,具体如下:
d7695e27e19e41c0af85476fdb249112.png
1. LinkedList实现了 List接口
2. LinkedList的底层使用了 双向链表
3. LinkedList没有实现RandomAccess接口,因此LinkedList 不支持随机访问
4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

二、LinkedList的使用

构造方法:

方法解释
LinkedList()
无参构造
public LinkedList(Collection<? extends E> c)
使用其他集合容器中元素构造List
public static void main(String[] args) { // 构造一个空的LinkedList List<Integer> list1 = new LinkedList<>();List<String> list2 = new java.util.ArrayList<>(); list2.add("JavaSE");list2.add("JavaWeb"); list2.add("JavaEE"); // 使用ArrayList构造LinkedList List<String> list3 = new LinkedList<>(list2); 
}

 LinkedList的常用方法:

方法解释
boolean add(E e)
尾插 e
void add(int index, E element)
将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c)
尾插 c 中的元素
E remove(int index)
删除 index 位置元素
boolean remove(Object o)
删除遇到的第一个 o
E get(int index)
获取下标 index 位置元素
E set(int index, E element)
将下标 index 位置元素设置为 element
void clear()
清空
boolean contains(Object o)
判断 o 是否在线性表中
int indexOf(Object o)
返回第一个 o 所在下标
int lastIndexOf(Object o)
返回最后一个 o 的下标
List<E> subList(int fromIndex, int toIndex)
截取部分 list

LinkedList的遍历:(foreach遍历、使用迭代器遍历---正向遍历、使用反向迭代器---反向遍历

LinkedList<String> list = new LinkedList<>();list.add("javaSE");list.add("javaWeb");list.add("javaEE");// foreach遍历for (String x: list) {System.out.print(x + " ");}// 使用迭代器遍历---正向遍历ListIterator<String> list1 = list.listIterator();while (list1.hasNext()){System.out.print(list1.next()+" ");}// 使用反向迭代器---反向遍历ListIterator<String> lis2 = list.listIterator(list.size());while (lis2.hasPrevious()){System.out.print(lis2.previous()+" ");}

三、LinkedList自实现

public class MyLinkedList {static class ListNode{int val;ListNode pre;ListNode next;public ListNode(int val){this.val = val;}}public ListNode head;//头部public ListNode tail;//尾部public void addFirst(int data){ListNode node = new ListNode(data);if (head == null){head = node;tail = node;return;}node.next = head;head.pre = node;head = node;}public void addLast(int data){ListNode node = new ListNode(data);if (head == null){head = node;tail = node;return;}tail.next = node;node.pre = tail;tail = node;}//任意位置插入,第一个数据节点为0号下标public boolean addIndex(int index,int data){if (index < 0 || index > size()){System.out.println("index位置不合法!");return false;}if (index == 0){addFirst(data);return true;}if (index == size()){addLast(data);return true;}ListNode indexNode = findNode(index);ListNode node = new ListNode(data);node.pre = indexNode.pre;indexNode.pre.next = node;node.next = indexNode;indexNode.pre = node;return true;}public ListNode findNode(int index){ListNode cur = head;while (index != 0){cur = cur.next;index--;}return cur;}public boolean contains(int key){ListNode cur = head;while (cur != null){if (cur.val == key)return true;cur = cur.next;}return false;}public void remove(int key) {ListNode cur = head;while (cur != null) {if (cur.val == key) {if (cur == head) {head = head.next;if (head != null) {head.pre = null;} else {tail = null;}} else {cur.pre.next = cur.next;if (cur.next != null) {cur.next.pre = cur.pre;} else {tail = tail.pre;}}return;}cur = cur.next;}}public void removeAllKey(int key) {ListNode cur = head;while (cur != null) {if (cur.val == key) {if (cur == head) {head = head.next;if (head != null) {head.pre = null;} else {tail = null;}} else {cur.pre.next = cur.next;if (cur.next != null) {cur.next.pre = cur.pre;} else {tail = tail.pre;}}}cur = cur.next;}}public int size(){ListNode cur = head;int count = 0;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;}}public void clear(){ListNode cur = head;while (cur != null){ListNode temp = cur.next;cur.next = null;cur.pre = null;cur = temp;}head = null;tail = null;}
}

四、链表实现逆序打印的两种方式(递归和非递归)

递归逆序打印:

public void display(ListNode head) {if(head == null) {return;}if(head.next == null) {System.out.print(head.val+" ");return;}display(head.next);System.out.print(head.val+" ");}

非递归逆序打印(用栈实现):

public void display(ListNode head) {if (head == null) {return;}Stack<ListNode> stack = new Stack<>();ListNode cur = head;while (cur != null) {stack.push(cur);cur = cur.next;}while (!stack.empty()) {ListNode ret = stack.pop();System.out.print(ret.val+" ");}}

 

五、ArrayList和LinkedList有什么区别?

 

ArrayList实质是顺序表,底层是一个数组。LinkedList实质是一个链表。

他们都具有增删查改的功能,但是在实现方式上有区别。比如在插入元素的时候,ArrayList往0位置上插入一个元素,就需把整个数组整体往后移动,时间复杂度为O(N)。而LinkedList只需要修改指向就可以了,时间复杂度为O(1)。但是ArrayList可以支持随机访问,时间复杂度为O(1),所以一般情况下ArrayList顺序表适合频繁根据下标位置访问,LinkedList比较适合插入和删除比较频繁的情况。

从存储上来说,ArrayList顺序表在物理上和逻辑上都是连续的,但是在扩容的时候,可能会造成空间的浪费。而LinkedList在物理上不一定是连续的,在逻辑上是连续的,可以做到随用随取。

不同点ArrayListLinkedList
存储空间上         
物理上逻辑上一定连续
逻辑上连续,但物理上不一定连续
随机访问
支持O(1)
不支持:O(N)
头插
需要搬移元素,效率低O(N)
只需修改引用的指向,时间复杂度为O(1)
插入
空间不够时需要扩容
没有容量的概念
应用场景
元素高效存储+频繁访问
任意位置插入和删除频繁

 

 


http://chatgpt.dhexx.cn/article/9pamRU4i.shtml

相关文章

LinkedList用法详解

一、LinkedList简单介绍 LinkedList是List接口的实现类&#xff0c;因此也实现了List的方法。但LinkedList是采用链表结构的方式来实现List接口的&#xff0c;因此在进 行insert 和remove动作时效率要比ArrayList高。 二、LinkedList的用法介绍 1、add和push 通过这两种方法均…

Java集合类——LinkedList(单链表及双链表)

一&#xff0c;ArrayList的缺陷 1.空间浪费 在之前的博客中&#xff0c;我利用源码详细的讲解了ArrayList这个集合类&#xff08;尤其是扩容机制&#xff09;&#xff0c;可以知道ArrayList的底层主要是一个动态的可变数组&#xff0c;容量满的时候需要进行1.5倍扩容。但是我…

java学习之LinkedList(链表)

LinkedList&#xff1a;一种线性表&#xff0c;但不按照线性顺序存储数据&#xff08;实际上为链表&#xff09;。 链表分为单向链表和双向链表&#xff0c;实际应当还有循环链表。 单向链表&#xff1a;将一个区域分成两部分&#xff0c;分别为节点区域和数据域。 如下图所…

LinkedList和ArrayList对比各有什么优势?

一、LinkedList的概述 1. LinkedList是双向链表实现的List 2. LinkedList是非线程安全的 3. LinkedList元素允许为null&#xff0c;允许重复元素 4. LinkedList是基于链表实现的&#xff0c;因此插入删除效率高&#xff0c;查找效率低(虽然有一个加速动作) 5. LinkedList是…

LinkedList详解

文章目录 介绍继承体系 LinkedLists实现底层数组结构构造函数getFirst(),getLast()removeFirest(),removeLast(),remove(e),remove(index)删除head元素删除last元素add()addAll()clear()查找操作遍历 介绍 LinkedList同时实现了List接口和Deque对口&#xff0c;也就是收它既可…

Chrome被百度网页劫持

Chrome被百度劫持的解决办法 浏览器的运行太慢了&#xff0c;就想试试谷歌的浏览器&#xff0c;但是每次打开的都是百度的界面&#xff0c;明显就是被劫持了&#xff0c; 看了网上的好多方法都没有什么明显的效果 问题 在使用Chrome浏览器打开后直接弹出一个百度的界面这看着就…

网页被劫持怎么修复?主页被劫持修复方法

电脑的浏览器被劫持了应该怎么解决&#xff1f;小编今天就来教大家解决电脑浏览器自动跳转到一个网页中的问题。 方法步骤 1.随着网络的兴起&#xff0c;更多的小伙伴享受到网络带来的便利生活&#xff0c;其中上网浏览就是非常受欢迎的一个功能&#xff0c;但是很多不法分子看…

Google Chrome主页被iduba劫持解决方法

今天用电脑的时候发现google的主页被改成了iduba的主页&#xff0c;烦的一比&#xff0c;看了好久才解决1.查看chrome://version 在命令行处会发现带有iduba的网站&#xff0c;我这里解决了&#xff0c;就没有了 2.点开google快捷方式的属性进行修改 将命令行中的代码全部复制…

浏览器被劫持怎么解决?关于浏览器被劫持主页的处理方法

背景: 上个月重做了win10系统,系统激活过程中没有出现任何问题。重装office套装,使用暴风激活下载地址: (http://win.shibojiaa.cn/baofeng/)激活office套装后,发现所有浏览器主页被劫持。打开任何一个浏览器地址栏中显示:(http://uj7.gndh555.top/)随后跳转hao123。…

Microsoft edge 主页被劫持的处理办法

最根本的办法&#xff0c;如果是任务栏固定打开后发现主页被劫持&#xff0c;应该是弄明白任务栏的链接是来自电脑的开始页面还是桌面的快捷方式。 如果是开始界面应用固定于任务栏&#xff0c;那么找到开始界面的Microsoft edge&#xff0c;右键然后找到所在文件夹。 找到开始…

浏览器主页被劫持,跳转hao123解决办法!

劫 持 指 南 前戏-疑难杂症小妙招 当打开电脑准备划水时&#xff0c;结果一打开浏览器&#xff0c;就发现它自动打开一个新的链接&#xff0c;紧接着又跳转到一个特定网页上去了&#xff0c;大家肯定心里那个气啊&#xff0c;打开百度一顿搜索&#xff0c;试了各种方法都不行…

百度主页被“/?tn=88093251_85_hao_pg“劫持的一种解决办法

前言 在闲暇之余换了个系统&#xff0c;为了方便使用了在线的小白一键装机安装的win10专业版&#xff0c;先抛开携带的各种垃圾软件不说&#xff0c;最不爽的还是主页无论如何修改都被百度劫持。 内容 尝试了网上各种解决办法&#xff0c;其中包括但不限于&#xff1a; 下…

Chrome主页被劫持怎么破

之前遇到Chrome被2345劫持了&#xff0c;导致的结果是每天初次打开Chrome都会进入2345的流氓主页&#xff0c;尝试了若干解决办法&#xff0c;最终得以解决。现简要记录一下所尝试过的方法以及解决过程&#xff0c;以下所涉及到的任何一种能够方法都有可能导致Chrome浏览器的劫…

教你解决浏览器被360劫持篡改主页的麻烦

前言 相信很多的小伙伴都遇到一个问题&#xff0c;就是好端端的&#xff0c;打开自己的edge或者Chrome&#xff0c;突然发现自己的主页变成了这样&#xff08;下图&#xff09; 不得不说&#xff0c;这个看得人真的不适。&#xff08;晕&#x1f635;&#xff09;相信大部分人还…

Motan RPC

中文文档&#xff1a;https://github.com/weibocom/motan/wiki/zh_userguide#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E 微信公众号

Motan整体结构详述

简述 Motan是一套高性能、易于使用的分布式远程服务调用(RPC)框架。 文章结构 1.调用详解 2.注册中心 3.支持的协议 4.配置概述 5.注解配置 6.架构概述 7.模块概述 8.运维监控 高清原图见脑图地址http://naotu.baidu.com/file/2832af5a32a02ea63bb0e826a966d502?token4e7921e3…

motan源码分析三:与spring框架的结合

在本文第一章&#xff0c;分析的demo中使用了代码加载的方式加载了相关的类&#xff0c;但在我们的实际工作中&#xff0c;使用spring来加载相关的类的情况会更多&#xff0c;本文将分析一下motan是如何与spring一起协同工作的&#xff0c;主要的原理就是利用了spring支持的自定…

motan源码分析一:服务发布及注册

motan是新浪微博开源的服务治理框架&#xff0c;具体介绍请看&#xff1a;http://tech.sina.com.cn/i/2016-05-10/doc-ifxryhhh1869879.shtml. 本系列的文章将分析它的底层源码&#xff0c;分析的源码版本为&#xff1a;0.1.2。第一篇文章将以服务的发布和注册开始&#xff0c;…

轻量级Rpc框架设计--motan源码解析六:client端服务发现

一, Client端初始化工作 client端通过RefererConfigBean类实现InitializingBean接口的afterPropertiesSet方法, 进行下面三项检查配置工作: ①checkAndConfigBasicConfig(); // 检查并配置basicConfig ②checkAndConfigProtocols(); //检查并配置protocols ③checkAndConfi…

java rpc motan_【RPC 专栏】Motan 中使用异步 RPC 接口

为什么慢&#xff1f; 多线程加速 异步调用 RPC 异步调用 总结 这周六参加了一个美团点评的技术沙龙&#xff0c;其中一位老师在介绍他们自研的 RPC 框架时提到一点&#xff1a;RPC 请求分为 sync&#xff0c;future&#xff0c;callback&#xff0c;oneway&#xff0c;并且需要…