【Java数据结构】详解LinkedList与链表(一)

🔒文章目录:

1.❤️❤️前言~🥳🎉🎉🎉

2.ArrayList的缺陷

3.链表的概念及结构

4.无头单向非循环链表的实现 

4.1成员属性

4.2成员方法

         createList 

display——打印链表 

addFirst——头插

 addLast——尾插

 size——获取单链表长度

addIndex——在任意位置插入 

 contains——判定是否包含某个元素

remove——删除第一次出现关键字为key的结点

 removeAll——删除所有值为key的结点 

clear——清空单链表 

 4.3完整代码及使用

  完整代码 

  完整代码的使用

5.总结


 1.❤️❤️前言~🥳🎉🎉🎉

Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。

如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的内容感兴趣,记得关注我👀👀以便不错过每一篇精彩。

当然,如果在阅读中发现任何问题或疑问,我非常欢迎你在评论区留言指正🗨️🗨️。让我们共同努力,一起进步!

加油,一起CHIN UP!💪💪

🔗个人主页:E绵绵的博客
📚所属专栏:

1. JAVA知识点专栏

        深入探索JAVA的核心概念与技术细节

2.JAVA题目练习

        实战演练,巩固JAVA编程技能

3.c语言知识点专栏

        揭示c语言的底层逻辑与高级特性

4.c语言题目练习

        挑战自我,提升c语言编程能力

📘 持续更新中,敬请期待❤️❤️

借鉴文章:Java【链表】详细图解/ 模拟实现+【LinkedList】常用方法介绍_java linkedlist方法-CSDN博客

2.ArrayList的缺陷

上篇文章已经熟悉了ArrayList的使用,并且进行了简单模拟实现。通过源码知道,ArrayList底层使用数组来存储元素

但由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后 搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。

所以:java 集合中又引入了LinkedList,即链表结构。

3.链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 


 注意:

1.从上图可看出,链式结构在逻辑上是连续的,但是在物理上不一定连续

2.其结点一般都是从堆上申请出来的

3.从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续


🎯🎯实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:


1. 单向或者双向


2.带头或者不带头


3. 循环或者非循环

虽然有这么多的链表的结构,但是我们重点掌握两种:


1.无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如 哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2.无头双向非循环链表:在Java的集合框架库中LinkedList底层实现就是无头双向非循环链表。

4.无头单向非循环链表的实现 

4.1成员属性

 要模拟实现链表,也得自己实现一个类,首先要考虑这个类中的成员属性

已经说过,链表是由多个结点 “链接” 而成的,那么需要定义一个 静态内部类 Node:其中有两个域:
📌值域 value :来记录这个结点的值
📌指针域 next:来记录下一个结点的地址

📌并且它还需要一个构造方法:在创建ListNode内部类的同时分配好value的值。

📌模拟的链表中还需要一个 成员变量:head 来记录当前链表的头结点。 

​
public class SingleLinkedList {static  class  ListNode{public   int value;public   ListNode next;public ListNode(int value) {this.value = value;}}public ListNode head;​

 4.2成员方法

  createList 

该方法是我们自己为了方便独创的,实际链表方法中并不存在该方法。

 public void createList(){ListNode listNode1 = new ListNode(45);ListNode listNode2 = new ListNode(46);ListNode listNode3 = new ListNode(50);ListNode listNode4 = new ListNode(56);ListNode listNode5 = new ListNode(67);listNode1.next=listNode2;listNode2.next=listNode3;listNode3.next=listNode4;listNode4.next=listNode5;head=listNode1;}

该方法创建了一个内部节点为5个的无头单向非循环链表。(注意结尾head要指向ListNode1,否则该链表之后会自动被释放掉)

display——打印链表 

   注意:LinkedList 中不存在该方法,为了方便看测试结果

  public void display(){ListNode cur=head;while(cur!=null){System.out.print(cur.value+" ");cur=cur.next;}System.out.println();}

addFirst——头插

❗️❗️和顺序表不同,链表是由一个个结点组成的,而顺序表可以理解为一个数组
顺序表插入之前必须考虑数组是否以及满了,而链表只需要关心各个结点的next即可。

因为我们还有一个成员属性:head,是用来记录头结点的
所以链表的头插操作就是:
1️⃣new 一个结点 node,类型是 Node
2️⃣链接:把头结点的地址( head 的值)赋给 node 的指针域 next
3️⃣head 记录新的头结点

 
public void  addFirst(int a){ListNode listNode = new ListNode(a);listNode.next=head;head=listNode;
}

 addLast——尾插

尾插步骤:
1️⃣new 一个 node,类型是 Node
2️⃣找到尾结点
3️⃣链接:把 node 的值(也就是地址)赋给尾结点的指针域 next

🚗🚗🚗
如何找到尾结点呢❓
需要 从头结点开始,遍历链表,找到一个结点的指针域 next 域为 null,它就是尾结点✅

head 是用来标记头结点的,所以 head 不能随意更改
我们需要再定义一个 Node 类型的 cur,让 cur 遍历链表

当 cur 找到尾结点后,需要让此时的尾结点和新结点 node 连接上
即如下图:

并且我们还需要注意一个特殊情况:

cur 这个变量中存放的值 要更改为下一个结点的地址:cur = cur.next;但当cur == null 时,这里就会发生空指针异常❌,那么在实例中是否会出现这种情况?

如果 head 一开始就是 null ,也就是链表为空时,cur 就会被 head 赋值成 null,就会发生空指针异常。所以当链表为空时,就不需要遍历链表找尾结点,直接把 node 的值赋给 head 即可。


public void  addLast(int a){ListNode listNode = new ListNode(a);ListNode cur=head;if(head==null){head=listNode;return;
}while(cur.next!=null){cur=cur.next;}cur.next=listNode;
}

 size——获取单链表长度

   直接遍历链表即可

public int size(){int count=0;ListNode cur=head;while(cur!=null){cur=cur.next;count++;}return count;}

addIndex——在任意位置插入 

官方规定第一个数据的位置是0,和数组的位置(下标)规则一致

所以我们首先要判断 index 的合法性:index<0 || index >链表长度是不合法❌的


index 合法的情况下,如何在index位置插入删除呢❓
📌index == 0就是头插
📌index = 链表长度就是尾插
❗️主要是链表中间位置的插入和删除

要想在两个结点中间插入新结点,首先要找到这两个结点的地址
找到 index -1 结点的位置也就相当于找到了 index 结点的位置

找到其位置很简单,cur 遍历链表 index-1 次即可


具体插入步骤:

1️⃣node.next = prevIndex.next;
2️⃣prevIndex.next = node;

这两行不能交换位置❗️❗️❗️
如果先让 prevIndex.next = node;那么就会丢失 index 位置的那个结点↪️,此时 node.next = prevIndex.next 就相当于 node.next = node;代码会发生错误❌


注意还有一个特殊点当链表中无任何节点,为null时,无论index为何值,都会直接添加一个节点。


public void addIndex(int index,int a){if(head==null){ListNode listNode = new ListNode(a);head=listNode;return;}if(index<0||index>size()){System.out.println("位置不合法");//这里就不搞抛出异常了,我们简单点return;}if(index==0){addFirst(a);return;}if(index==size()){addLast(a);return;}ListNode listNode = new ListNode(a);ListNode cur=head;for (int i = 0; i <index-1 ; i++) {cur=cur.next;}listNode.next=cur.next;cur.next=listNode;
}

 contains——判定是否包含某个元素

比较简单,遍历这个数组即可

public void  contain(int key){ListNode cur=head;while(cur!=null){if(cur.value==key){System.out.println(true);return;}cur=cur.next;}System.out.println(false);
}

因为这里我们存放的是 int 类型的变量,但 LinkedList 当中是存放引用数据类型的
⚠️⚠️⚠️当表中是引用类型时,就不可以用“等号”比较,应该用 equals 方法

remove——删除第一次出现关键字为key的结点

1️⃣如果链表为空就不能再删了
2️⃣如果头结点就是要删除的 key 结点,直接 head 存放下一个结点的地址
3️⃣如果链表其他结点是要删除的 key 结点,要先找到 key 结点的前一个结点

当 key 结点的前一个结点的 next 不再存放 key 结点地址时,key 结点此后不会再被使用,会被系统自动回收🗑️

所以完整代码如下:

public void remove(int key){ListNode cur=head;if(head==null) {System.out.println("为空链表,不能进行删除操作");return;}if(cur.value==key) {head=head.next;return;}while(cur.next!=null){if(cur.next.value==key){cur.next=cur.next.next;return;}cur=cur.next;}System.out.println("不存在该数");
}

 removeAll——删除所有值为key的结点 

这里我们将cur从head处开始检验:

当cur的下一个节点中的值等于key时:    cur.next=cur.next.next,否则cur=cur.next。

最后检测完毕后还要看一下head处的值是否等于key,如果等于则将head=head.next。


完整代码如下:

public void removeAll(int key){if(this.head == null) {System.out.println("为空链表,不能进行删除操作");return;}ListNode cur = head;while(cur.next != null){if(cur.next.value == key){cur.next=cur.next.next;}else {cur = cur.next;}}if(head.value==key){head = head.next;}}

clear——清空单链表 

head 这个变量一直存放着链表的头结点位置,把head置空,就找不到此链表,那么链表中的所有结点都会被系统自动回收🗑️

    public void clear() {head = null;}

 4.3完整代码及使用

  完整代码 

public class SingleLinkedList {static  class  ListNode{public   int value;public   ListNode next;public ListNode(int value) {this.value = value;}}public ListNode head;public void createList(){ListNode listNode1 = new ListNode(45);ListNode listNode2 = new ListNode(46);ListNode listNode3 = new ListNode(50);ListNode listNode4 = new ListNode(56);ListNode listNode5 = new ListNode(67);listNode1.next=listNode2;listNode2.next=listNode3;listNode3.next=listNode4;listNode4.next=listNode5;head=listNode1;}public void display(){ListNode cur=head;while(cur!=null){System.out.print(cur.value+" ");cur=cur.next;}System.out.println();}public int size(){int count=0;ListNode cur=head;while(cur!=null){cur=cur.next;count++;}return count;}
public void  contain(int key){ListNode cur=head;while(cur!=null){if(cur.value==key){System.out.println(true);return;}cur=cur.next;}System.out.println(false);
}public void  addFirst(int a){ListNode listNode = new ListNode(a);listNode.next=head;head=listNode;
}
public void  addLast(int a){ListNode listNode = new ListNode(a);ListNode cur=head;if(head==null){head=listNode;return;
}while(cur.next!=null){cur=cur.next;}cur.next=listNode;
}public void addIndex(int index,int a){if(head==null){ListNode listNode = new ListNode(a);head=listNode;return;}if(index<0||index>size()){System.out.println("位置不合法");//这里就不搞抛出异常了,我们简单点return;}if(index==0){addFirst(a);return;}if(index==size()){addLast(a);return;}ListNode listNode = new ListNode(a);ListNode cur=head;for (int i = 0; i <index-1 ; i++) {cur=cur.next;}listNode.next=cur.next;cur.next=listNode;
}public void remove(int key){ListNode cur=head;if(head==null) {System.out.println("为空链表,不能进行删除操作");return;}if(cur.value==key) {head=head.next;return;}while(cur.next!=null){if(cur.next.value==key){cur.next=cur.next.next;return;}cur=cur.next;}System.out.println("不存在该数");
}public void removeAll(int key){if(this.head == null) {System.out.println("为空链表,不能进行删除操作");return;}ListNode cur = head;while(cur.next != null){if(cur.next.value == key){cur.next=cur.next.next;}else {cur = cur.next;}}if(head.value==key){head = head.next;}}public void clear(){head=null;}}

  完整代码的使用

public class Test {public static void main(String[] args) {SingleLinkedList singleLinkedList = new SingleLinkedList();singleLinkedList.createList();singleLinkedList.display();System.out.println(singleLinkedList.size());singleLinkedList.contain(45);singleLinkedList.addFirst(12);singleLinkedList.addLast(67);singleLinkedList.addIndex(3, 22);singleLinkedList.display();singleLinkedList.remove(22);singleLinkedList.remove(12);singleLinkedList.display();singleLinkedList.removeAll(67);singleLinkedList.display();System.out.println("=======================");singleLinkedList.clear();//清空该链表singleLinkedList.display();System.out.println("已清空该链表");System.out.println("=======================");}}

5.总结

所以,我们在本文中详细讲述了链表的概念和结构,并成功模拟了无头非循环单链表的实现。在下篇文章中,我们将带来一些关于单链表的面试题。在此,我们诚挚地邀请各位大佬们为我们点赞、关注,并在评论区留下您宝贵的意见与建议。让我们共同学习,共同进步,为知识的海洋增添更多宝贵的财富!🎉🎉🎉❤️❤️💕💕🥳👏👏👏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/20314.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

少样本学习与零样本学习:理解与应用

少样本学习与零样本学习&#xff1a;理解与应用 在现代机器学习领域中&#xff0c;少样本学习&#xff08;Few-Shot Learning&#xff09;和零样本学习&#xff08;Zero-Shot Learning&#xff09;正变得越来越重要。这些技术能够在数据稀缺的情况下有效地进行学习和推理&…

2024就业寒潮下的挑战与机遇:能否守住饭碗,人工智能能否成为新春天?

前言 随着时代的飞速发展&#xff0c;2024年的就业市场迎来了前所未有的挑战。数以百万计的高校毕业生涌入市场&#xff0c;使得就业竞争愈发激烈。然而&#xff0c;在这股就业寒潮中&#xff0c;我们也看到了新的曙光——人工智能的崛起。这一新兴行业以其独特的魅力和巨大的…

深入分析 Android Service (五)

文章目录 深入分析 Android Service (五)1. 深入分析 Service 与 Activity 之间的通信2. Messenger 的内部工作原理2.1 服务端实现2.2 客户端实现 3. AIDL 的内部工作原理3.1 定义 AIDL 接口3.2 服务端实现3.3 客户端实现 4. Service 的优化建议和最佳实践4.1 异步操作4.2 资源…

【Linux】权限的概念

1.Linux权限的概念 Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;、普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受权限限制 普通用户&#xff1a;在linux下做有限的事情&#xff0c;受权限设置。 windows下也有超级用户…

Object.entries方法的使用

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组。 有以下需求&#xff1a; let cpuData reactive([{ label: 总量, content: test },{ label: 已使用, content: test },{ label: 未使用, content: test } ])<el-form label-position"left" l…

环卫车北斗GPS视频监控定位解决方案的应用与优势

一、引言 随着城市化进程的加快&#xff0c;环卫车作为城市环境卫生的重要保障力量&#xff0c;其运行效率与安全性直接关系到城市形象与居民生活品质。然而&#xff0c;传统的环卫车管理模式往往存在信息不对称、调度不合理、行驶不规范等问题&#xff0c;导致城市道路污染和…

微信小程序对接发货功能

注&#xff1a;微信小程序对接发货功能 文档地址&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html php代码 common.php use think\Config; use think\Db; use fast\Http; us…

LabVIEW远程开发与调试

在现代项目开发中&#xff0c;远程开发与调试已经成为一种常见的模式&#xff0c;特别是在使用LabVIEW进行工程项目时。本文将详细分析LabVIEW远程开发与调试的优缺点&#xff0c;并从多个角度说明如何建议客户采用这种方式&#xff0c;以提高项目效率和质量。 优点 灵活性和便…

Linux【安全 02】OpenSSH漏洞修复(离线升级最新版本流程)网盘分享3个安装包+26个离线依赖

OpenSSH离线升级最新版本流程 1. 漏洞信息2. 环境说明3.依赖安装3.1 在线安装3.2 离线安装 4.备份卸载4.1 备份4.2 卸载旧版本 5.安装5.1 zlib5.2 ssl5.3 openssh5.3.1 安装5.3.2 配置 6.脚本整理7.文件资源 本文仅针对CentOS7.8版本&#xff0c;其他版本未测试&#xff0c;安装…

GSM信令流程(附着、去附着、PDP激活、修改流程)

1、联合附着流程 附着包括身份认证、鉴权等 2、去附着流程 用户发起去附着 SGSN发起去附着 HLR发起去附着 GSSN使用S4发起去附着 3、Activation Procedures(PDP激活流程) 4、PDP更新或修改流程 5、Deactivate PDP Context 6、RAU(Routeing Area Update)流程 7、鉴权加…

生成式AI,在云端的绽放与盛开

编辑&#xff1a;阿冒 设计&#xff1a;沐由 毫无疑问&#xff0c;生成式AI已然成为当今技术发展和应用创新的重要引擎之一。 过去的一年多时间里&#xff0c;我们每个人都在目睹和见证着生成式AI是如何以移山倒海的力量&#xff0c;为诸多行业带来革命性乃至颠覆性的变革&…

新版校园跑腿外卖独立版+APP+小程序前端外卖配送平台源码

同城校园跑腿外卖配送平台源码&#xff0c;这套目前全网还没有人分享过&#xff0c;这个是开源的&#xff0c;所以没有任何问题了&#xff0c;这套源码非常吊&#xff0c;支持自定义diy 你可以设计你的页面&#xff0c;设计你自己的风格&#xff0c;支持多校园&#xff0c;独立…

深度学习中的模型架构详解:RNN、LSTM、TextCNN和Transformer

深度学习中的模型架构详解&#xff1a;RNN、LSTM、TextCNN和Transformer 文章目录 深度学习中的模型架构详解&#xff1a;RNN、LSTM、TextCNN和Transformer循环神经网络 (RNN)RNN的优点RNN的缺点RNN的代码实现 长短期记忆网络 (LSTM)LSTM的优点LSTM的缺点LSTM的代码实现 TextCN…

mac电脑安卓设备文件传输助手:MacDroid pro 中文激活版

MacDroid Pro是一款专为Mac电脑和Android设备设计的软件&#xff0c;旨在简化两者之间的文件传输和数据管理&#xff0c;双向文件传输&#xff1a;支持从Mac电脑向Android设备传输文件&#xff0c;也可以将Android设备上的文件轻松传输到Mac电脑上。完整的文件访问和管理&#…

机器学习笔记 - PyTorch 分布式训练概览

一、简述 对于大规模的数据集,只能进行分布式训练,分布式训练会尽可能的利用我们的算力,使模型训练更加高效。PyTorch提供了Data Parallel包,它可以实现单机、多GPU并行。 PyTorch 数据并行模块的内部工作原理 上面的图像说明了PyTorch 如何在单个系统中利用多个 G…

目标检测——无人机搜索救援数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

springboot项目banner生成器

Spring Boot banner在线生成工具&#xff0c;制作下载英文banner.txt&#xff0c;修改替换banner.txt文字实现自定义&#xff0c;个性化启动banner-bootschool.netSpring Boot banner工具实现在线生成banner&#xff0c;轻松修改替换实现自定义banner&#xff0c;让banner.txt文…

基于Lumerical fdtd进行无序光子晶体波导的仿真设计及优化

光子晶体是一类通过不同折射率介质周期性的排列而形成的具有光波长量级的周期性人工微型结构&#xff0c;相比于传统晶体来说&#xff0c;由于介电函数的周期性分布&#xff0c;光子晶体也会产生一些类似于传统晶体的带隙&#xff0c;使光局域在带隙中无法传播。我们在完整的光…

Linux - 文件管理高级2

3.处理字符 sed ① sed 默认情况下不会修改原文件内容 ② sed 是一种非交互式的编辑器 3.1 工作原理 将原文件一行一行的进行处理&#xff0c;取出一行&#xff0c;放入“模式空间进行处理”&#xff0c;处理完成之后将结果输出到屏幕上&#xff0c;然后读取下一行&#xf…

智慧启航 网联无限丨2024高通汽车技术与合作峰会美格智能分论坛隆重举行

5月30日下午&#xff0c;以“智慧启航 网联无限”为主题的2024高通汽车技术与合作峰会&美格智能分论坛在无锡国际会议中心隆重举行&#xff0c;本次论坛由高通技术公司与美格智能技术股份有限公司共同主办&#xff0c;上海市车联网协会、江苏省智能网联汽车产业创新联盟、江…