【Java数据结构】---List(LinkedList)
乐观学习,乐观生活,才能不断前进啊!!!
我的主页:optimistic_chen
我的专栏:c语言 ,Java
欢迎大家访问~
创作不易,大佬们点赞鼓励下吧~
文章目录
- 前言
- 链表(MySingleList)
- 具体功能代码
- LinkedList简介
- LinkedList的模拟实现
- LinkedList的使用
- LinkedList的构造
- LinkedList的方法
- LinkedList的遍历
- ArrayList和LinkeddList的区别
- 完结
前言

上篇博客详细写了ArrayList的相关问题,包括上图(极其重要),我会在最近几篇博客中都有附上。
ArrayList的优点很明显,底层逻辑是一个数组,它通过下标去访问数据的速度非常快。但是在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低
所以java集合框架中引入了LinkedList类,即链表结构。
链表(MySingleList)
链表,作为线性表的一种,它与顺序表截然相反:链表是一种物理存储结构 上 非连续存储结构, 数据元素的逻辑顺序是通过链表中的引用 链接次序实现的
之前C语言了解过这方面的知识C语言—链表专题,所以我们有一定的基础,我相信链表对于大家一定是熟悉的存在。我们先由易入难,先自己尝试一下单链表(MySingleList)的功能实现,为接下来的 LinkedList(无头双向链表) 打下基础.
接口
public interface IList {public void addFirst(int data);public void addLast(int data);public void addIndex(int index,int data);public boolean contains(int key);public void remove(int key);public void removeAllKey(int key);public int size();public void clear();public void display();
}
具体功能代码
头插法
@Overridepublic void addFirst(int data) {ListNode node = new ListNode(data);node.next=head;head=node;}
尾插法
@Overridepublic void addLast(int data) {ListNode node =new ListNode(data);if(head==null){head = node;return;}ListNode cur=head;while(cur.next!=null){cur= cur.next;}cur.next=node;}
任意位置插入,第一个数据节点为0号下标
@Overridepublic void addIndex(int index, int data) {int len=size();if(index<0||index>len){System.out.println("index位置不合法");return;}if(index==0){addFirst(data);return;}if(index==len){addLast(data);return;}ListNode cur=head;while(index-1!=0){cur=cur.next;index--;}ListNode node=new ListNode(data);node.next= cur.next;cur.next=node;}
查找是否包含关键字key是否在单链表当中
@Overridepublic boolean contains(int key) {ListNode cur=head;while(cur!=null){if(cur.val==key){return true;}cur=cur.next;}return false;}
删除第一次出现关键字为key的节点
@Overridepublic void remove(int key) {if(head==null){return;}if(head.val==key){head=head.next;return;}ListNode cur=findNodeOfKey(key);if(cur==null){return;}ListNode del= cur.next;cur.next=del.next;}private ListNode findNodeOfKey(int key){ListNode cur=head;while(cur.next!=null) {if (cur.next.val == key) {return cur;}cur= cur.next;}return null;}
删除所有值为key的节点
@Overridepublic void removeAllKey(int key) {if(head==null){return;}ListNode prev=head;ListNode cur=head.next;while(cur!=null){if(cur.val==key){prev.next=cur.next;cur= cur.next;}else{prev=cur;cur= cur.next;}if(head.val==key){head=head.next;return;}}}
得到单链表的长度
@Overridepublic int size() {int len=0;ListNode cur=head;while(cur!=null){len++;cur=cur.next;}return len;}
清空链表
@Overridepublic void clear() {ListNode cur=head;while(cur!=null){ListNode curN=cur.next;cur.next=null;cur=curN;}head=null;}
LinkedList简介


LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
总结:
- LinkedList实现了List接口
- LinkedList的底层使用了双向链表
- LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
- LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
- LinkedList比较适合任意位置插入的场景
LinkedList的模拟实现

头插法
@Overridepublic void addFirst(int data) {ListNode node=new ListNode(data);if(head==null){head=last=node;}else{node.next=head;head.prev=node;head=node;}}
尾插法
@Overridepublic void addLast(int data) {ListNode node=new ListNode(data);if(head==null){head=last=node;}else{last.next=node;node.prev=last;last= last.next;}}
任意位置插入,第一个数据节点为0号下标
@Overridepublic void addIndex(int index, int data) {int len=size();if(index<0||index>len){return;}if(index==0){addFirst(data);return;}if(index==len){addLast(data);return;}ListNode cur=findIndex(index);ListNode node=new ListNode(data);node.next=cur;cur.prev.next=node;node.prev=cur.prev;cur.next=node;}
private ListNode findIndex(int index){ListNode cur=head;while(index!=0){cur= cur.next;index--;}return cur;}
查找是否包含关键字key是否在链表当中
@Overridepublic boolean contains(int key) {ListNode cur=head;int count=0;while(cur!=null){if(cur.val==key) {return true;}cur= cur.next;}return false;}
删除第一次出现关键字为key的节点
@Overridepublic void remove(int key) {ListNode cur=head;while(cur!=null){//开始删除if(cur.val==key){//有可能是头节点if(cur==head){head = head.next;if(head!=null){head.prev=null;}}else{cur.prev.next= cur.next;if(cur.next==null){//有可能是尾节点last= last.prev;}else{cur.next.prev= cur.prev;}}return;}else{cur = cur.next;}}}
删除所有值为key的节点
@Overridepublic void removeAllKey(int key) {ListNode cur=head;while(cur!=null){//开始删除if(cur.val==key){//有可能是头节点if(cur==head){head = head.next;if(head!=null){head.prev=null;}}else{cur.prev.next= cur.next;if(cur.next==null){//有可能是尾节点last= last.prev;}else{cur.next.prev= cur.prev;}}}else{cur = cur.next;}}}
LinkedList的使用
前面我们自主实现了LinkedList的各种方法,只是为了大家更好的理解和学习,以后做题可能会运用到类似的想法或思路,可以更加高效的完成题目,平时也可以直接使用LinkedList下的方法。如下图:

LinkedList的构造

public static void main(String[] args) {List<Integer> list1=new LinkedList<Integer>();LinkedList<Integer> list2 = new LinkedList<Integer>();//使用ArrayList构造LinkedList List<String> list3=new ArrayList<>();List<String> list4=new LinkedList<>(list3);}
为什么可以有的构造可以用List,有的用LinkedList,甚至出现了ArrayList?一切都是这张贯穿整个数据结构的图。

LinkedList的方法
public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1); // add(): 表示尾插list.add(2);list.add(3);list.add(4);list.add(5);list.add(6);list.add(7);System.out.println(list.size());System.out.println(list);// subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回List<Integer> list2 = list.subList(0, 3); System.out.println(list);System.out.println(list2);list.clear(); // 将list中元素清空System.out.println(list.size());
}
LinkedList的遍历
之前ArrayList博客【Java数据结构】—List(ArrayList) 讲过线性表的遍历,这次补充一下…
public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1); // add(): 表示尾插list.add(2);list.add(3);list.add(4);list.add(5);list.add(6);list.add(7);System.out.println(list.size());// 使用反向迭代器---反向遍历ListIterator<Integer> it = list.listIterator(list.size());while (it.hasPrevious()){System.out.print(it.previous() +" ");}
}
ArrayList和LinkeddList的区别
| 不同 | ArrayList | LinkedList |
|---|---|---|
| 存储空间 | 物理上一定连续 | 逻辑上连续,但物理上不一定连续 |
| 随机访问 | 支持O(1) | 不支持O(n) |
| 头插 | 空间不够时扩容 | 不存在容量的概念 |
| 运用场景 | 元素高效存储+频繁访问 | 频繁任意位置的插入和删除 |
完结
好了,到这里Java语法部分就已经结束了~
如果这个系列博客对你有帮助的话,可以点一个免费的赞并收藏起来哟~
可以点点关注,避免找不到我~ ,我的主页:optimistic_chen
我们下期不见不散~~Java
下期预告: 【Java数据结构】- - - List
相关文章:
【Java数据结构】---List(LinkedList)
乐观学习,乐观生活,才能不断前进啊!!! 我的主页:optimistic_chen 我的专栏:c语言 ,Java 欢迎大家访问~ 创作不易,大佬们点赞鼓励下吧~ 文章目录 前言链表(MyS…...
开发军用LabVIEW程序注意事项
在开发军用LabVIEW程序时,开发者需要从多个角度仔细考虑,以满足军方对安全性、可靠性、法规遵从性等方面的严格要求。由于军事系统通常涉及高度敏感的信息和严苛的环境条件,程序的设计必须保证数据的保密性、系统的稳定性以及与各种军事标准的…...
A3VLM: Actionable Articulation-Aware Vision Language Model
发表时间:13 Jun 2024 作者单位:SJTU Motivation:以往的机器人VLM如RT-1[4]、RT-2[3]和ManipLLM[21]都专注于直接学习以机器人为中心的动作。这种方法需要收集大量的机器人交互数据,这在现实世界中非常昂贵。 解决方法…...
企业高性能web服务器
web服务器介绍 Apache HTTP Server:也称为Apache,是一个开源的HTTP服务器,目前是全球使用最广泛的Web服务器 Nginx:Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器 Microsoft Internet Inform…...
数据库:深入解析SQL分组与聚合——提升数据查询效率的关键技巧
数据库:深入解析SQL分组与聚合——提升数据查询效率的关键技巧 在数据分析和数据库管理中,SQL 的分组与排序操作是不可或缺的工具。本篇博客将深入探讨 GROUP BY 和 ORDER BY 的使用方法,并通过实际案例说明如何通过分组实现数据聚合以及如何…...
【CSS】数字英文css没有转换成...换行点、没有换行、拆分的问题(非常常见的需求)
默认情况下,连续的英文或数字文本不会在空格处换行,这可能导致布局问题。 解决方案 要解决这个问题,可以使用以下几种CSS属性: word-break: 控制单词如何换行。设置为break-all可以让任何字符都能成为换行点。word-wrap: 控制是…...
C++ string模拟实现
一 如何区分自定义类与标准库中的同名类 // string.h #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include<iostream> using namespace std;namespace bit {class string{} }// Test.cpp include "string.h"int main() {return 0; } 既然要模拟实现str…...
Lora 全文翻译
作者: 地点:hby 来源:https://arxiv.org/pdf/2106.09685 工具:文心 LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS 摘要 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练,并适应特定任务或…...
结题阶段(2024年8月)
海门区教育科学 “十四五”规划2022年度立项课题 结题鉴定材料 课 题 名 称 高中信息技术项目化教学的研究与应用 课题负责人 郭书艳 所 在 单 位 江苏省包场高级中学 报 送 日 期 2024 年 6 月 20 日…...
贪吃蛇(C语言详解)
贪吃蛇游戏运行画面-CSDN直播 目录 贪吃蛇游戏运行画面-CSDN直播 1. 实验目标 2. Win32 API介绍 2.1 Win32 API 2.2 控制台程序(Console) 2.3 控制台屏幕上的坐标COORD 2.4 GetStdHandle 2.5 GetConsoleCursorlnfo 2.5.1 CONSOLE_CURSOR_INFO …...
国际以太网专线(IEPL)与国际专线(IPLC)服务
中国联通国际公司产品: 国际以太网专线 (IEPL)/国际专线(IPLC) 在全球化的今天,企业越来越依赖于高速、稳定且安全的国际网络连接来支持其跨国业务活动。中国联通国际公司作为中国领先的电信运营商之一,在这一领域提供了多种优质…...
vue 子父组件互相改值
在Vue.js中,子组件想要修改父组件的状态(如数据属性的值)时,通常遵循以下步骤: 父组件向子组件传递数据:通过props(属性)将需要被子组件操作的值传入子组件。例如,在父组…...
java之拼图小游戏(开源)
public class LoginJFrame extends JFrame {//表示登录界面,以后所有跟登录相关的都写在这里public LoginJFrame() {//设置界面的长和宽this.setSize(603,680);//设置界面的标题this.setTitle("拼图登陆界面");//设置界面置顶this.setAlwaysOnTop(true);/…...
Linux Shell批量测试IP连通性
Linux 通过Shell脚本来实现读取txt文件中的IP地址,并使用telnet对其后的所有端口进行测试,判断是否可以连接。每个IP地址的端口测试时间限制为5秒。 IP文件 : ips.txt 192.168.1.1 22,80,443 192.168.1.2 21,25,110 192.168.1.3 8080每一行包含一个IP地…...
已解决:anaocnda如何备份环境与安装环境
1.使用pip进行备份 激活对应的虚拟环境,切换到桌面或者想备份的位置。 备份即可: pip freeze > requirements.txt如何安装备份? pip install -r requirements.txt2.使用conda进行备份 激活对应的虚拟环境,切换到桌面或者想…...
自动化与高效设计:推理技术在FPGA中的应用
想象一下,你正在设计一个复杂的电路系统,就像在搭建一座精巧的积木城堡。你手头有各种形状和功能的积木块,这些积木块可以组合成任何你需要的结构。在这个过程中,你有两种主要的方法:一种是手动挑选和搭建每一块积木&a…...
对react模块和模块化理解
在React开发中,模块化和React模块是两个紧密相关但又有区别的概念。理解它们对于构建高效、可维护的React应用至关重要。 模块化 模块化是一种将大型代码库拆分成更小、更易于管理的部分(即模块)的软件设计技术。每个模块都封装了特定的功能…...
CAN总线-----帧格式
目录 前言 一、CAN总线帧格式分类 1.数据帧(重点) 2.遥控帧 3.错误帧 4.过载帧 5.间隔帧 二、位填充 三、波形实例 前言 本期我们就开始学习CAN总线的帧格式,对应帧格式的话,在前面我们学习I2C协议和SPI协议等协议的时候…...
UE网络同步(一) —— 一个项目入门UE网络同步之概念解释
最近在学习UE网络同步,发现了一个非常好的教程,并且附带了项目文件,这里从这个小项目入手,理解UE的网络同步 教程链接:https://www.youtube.com/watch?vJOJP0CvpB8w 项目链接:https://github.com/awforsyt…...
MATLAB中rsf2csf函数用法
目录 语法 说明 示例 将实数 Schur 形式变换为复数 Schur 形式 rsf2csf函数的功能是将实数 Schur 形式转换为复数 Schur 形式。 语法 [Unew,Tnew] rsf2csf(U,T) 说明 [Unew,Tnew] rsf2csf(U,T) 将实矩阵 X 的 [U,T] schur(X) 的输出从实数 Schur 形式变换为复数 Sc…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...

乐观学习,乐观生活,才能不断前进啊!!!