Collection与数据结构 链表与LinkedList (一):链表概述与单向无头非循环链表实现

1.ArrayList的缺点

上篇文章我们已经对顺序表进行了实现,并且对ArrayList进行了使用,我们知道ArrayList底层是使用数组实现的.
由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构。

2.链表

2.1 链表的概念与结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的.就像一列动车一样.
在这里插入图片描述
在这里插入图片描述
通过上图我们可以看到,一个链表中有一节一节的"车厢",还有中间的"链条".我们称每一节"车厢"为结点,我们可以看到每一个结点中有下一个结点的地址,链表就是通过存储节点的地址来连接起来的,还有该结点的值.上面就是我们需要重点掌握的一种链表类型,叫做单向无头非循环链表.其实链表还有好多类型,下面我们来展示.

2.2 链表的类型

链表有以下几种性质:有头/无头,单向/双向,循环/非循环

  1. 有头/无头
    在这里插入图片描述
    在这里插入图片描述
    它们的区别就是,有头链表的head永远指向一个固定的结点,而无头链表的head永远在改变.
  2. 单向/双向
    在这里插入图片描述

在这里插入图片描述
3. 循环/非循环
在这里插入图片描述
在这里插入图片描述
上面几种性质排列组合可以得到许多中链表的类型,这里我们重点掌握2中即可,一种是单向无头非循环,它在笔面试中经常出现,另一种是是无头双向循环链表,Java中的LinkedList底层就是通过它来实现的.

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

下面是要实现的接口,即链表中的常用方法:

public interface ILinkedList {void addFirst(int data);//尾插法void addLast(int data);//任意位置插入,第一个数据节点为0号下标void addIndex(int index,int data);//查找是否包含关键字key是否在单链表当中boolean contains(int key);//删除第一次出现关键字为key的节点void remove(int key);//删除所有值为key的节点void removeAllKey(int key);//得到单链表的长度int size();//清空链表void clear() ;//打印链表void display();}

下面我们来实现这些方法:

public class MyLinkedList implements ILinkedList {static class Node{public int val;public Node next = null;public Node(int val) {this.val = val;}}public Node head = null;/*** 创建默认链表*/public void createDeafultLinkedList(){Node node = new Node(23);this.head = node;Node node1 = new Node(34);node.next = node1;Node node2 = new Node(45);node1.next = node2;Node node3 = new Node(56);node2.next = node3;Node node4 = new Node(67);node3.next = node4;}/*** 在链表头部添加新的结点* @param data*/@Overridepublic void addFirst(int data) {Node node = new Node(data);
//        if(head == null){
//            head = node;
//        }else {
//            node.next = head;
//            head = node;
//        }//上面的代码其实没必要验证链表是否为空,head为null赋值过去还是nullnode.next = this.head;this.head = node;}/*** 在尾部添加新的结点* @param data*/@Overridepublic void addLast(int data) {Node node = new Node(data);Node cur = this.head;if (this.head == null){this.head = node;}else {while (cur.next != null){cur = cur.next;}cur.next = node;}}/*** 在指定位置添加结点* @param index* @param data*/@Overridepublic void addIndex(int index, int data) {if (index > size() || index < 0){throw new IndexExeption("下标有误");}Node node = new Node(data);if (this.head == null){this.head = node;return;//记得返回,不然会执行中间插入的代码}if (index == 0){//在链表头添加addFirst(node.val);return;}if (index == size()){//在链表尾部添加addLast(node.val);return;}//在中部添加Node cur = this.head;int count = 0;while (count != index-1){//寻找cur的前一个结点cur = cur.next;count++;}node.next = cur.next;cur.next = node;}/*** 检测链表中是否含有指定的值* @param key* @return*/@Overridepublic boolean contains(int key) {Node cur = this.head;while (cur != null){//先遍历链表if(cur.val == key){//在遍历的过程中如果等于,返回truereturn true;}cur = cur.next;}return false;}/*** 移除遇到的第一个值为key的元素* @param key*/@Overridepublic void remove(int key) {if (this.head == null){return;}if (head.val == key){head = head.next;return;}Node cur = findPreNode(key);//需要找到前一个结点才可以删除if (cur == null){//没找到要删除的结点return;}cur.next = cur.next.next;}private Node findPreNode(int key){//找到要删除结点的前一个结点Node cur = this.head;while (cur.next != null){//这里必须写成next不等于null,否则下面可能会出现空指针异常if (cur.next.val == key){return cur;}cur = cur.next;}return null;}/*** 移除所有符合值为key的结点* @param key*/@Overridepublic void removeAllKey(int key) {if (this.head == null){return;}Node pre = this.head;Node cur = this.head.next;//先不要管头结点,先删中间的while(cur != null){if (cur.val == key){pre.next = cur.next;}else {pre = pre.next;//若该结点不是要删除的结点,pre往后走}cur = cur.next;}//所有的都删完了,删除头结点if (head.val == key){head = head.next;}}/*** 计算链表大小* @return*/@Overridepublic int size() {int count = 0;Node cur = this.head;while (cur != null){count++;cur = cur.next;}return count;}/*** 清空链表*/@Overridepublic void clear() {head = null;//为被引用的结点会被JWM回收}/*** 打印链表*/@Overridepublic void display() {Node cur = this.head;while (cur != null){System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}/*** 从指定位置开始打印链表* @param node*/public void display(Node node) {Node cur = node;while (cur != null){System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}}

上面有几个问题需要注意

  1. 在中间插入元素的时候先要进行后链接,在进行前链接,如果先进行前链接,cur的下一个结点的地址就会丢失
  2. 在删除所有值为key的结点的时候,先删除head后符合条件的结点最后再处理head.

下面是对上述问题的动态演示:

[插入结点错误演示]

插入中间节点(错误)

[插入结点正确演示]

插入中间结点(正确)

[删除所有key结点]

删除所有key结点

下面我们对上述实现的方法进行测试:

*** 开始测试*/
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList = new MyLinkedList();myLinkedList.createDeafultLinkedList();myLinkedList.addFirst(11);myLinkedList.addLast(88);myLinkedList.display();System.out.println(myLinkedList.size());myLinkedList.addIndex(2,33);myLinkedList.display();System.out.println(myLinkedList.contains(11));System.out.println(myLinkedList.contains(12));myLinkedList.addIndex(1,23);myLinkedList.addIndex(1,23);myLinkedList.addIndex(1,23);myLinkedList.display();myLinkedList.remove(23);myLinkedList.display();myLinkedList.removeAllKey(23);myLinkedList.display();myLinkedList.clear();myLinkedList.display();}
}

测试结果:
在这里插入图片描述

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

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

相关文章

mysql 条件/系统/加密/其它函数

学习了日期时间函数&#xff0c;接着学习条件、系统、加密和其它函数。 3&#xff0c;条件判断函数 条件判断函数也称为控制流程函数&#xff0c;根据满足的条件的不同&#xff0c;执行相应的流程。MySQL中进行条件判断的函数有IF、IFNULL和 CASE。 函数 说明 IF(expr,v1,v2…

二叉树寻找祖先问题-算法通关村

二叉树寻找祖先问题-算法通关村 1 最近公共祖先问题 LeetCode236&#xff1a;给定一个二叉树&#xff0c;找到该树中两个指定节点的最近公共祖先。 最近公共祖先的定义为&#xff1a;“对于有根树T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足是…

代码随想录笔记|C++数据结构与算法学习笔记-动态规划(〇)|

本文是简单的视频总结&#xff1a;从此再也不怕动态规划了&#xff0c;动态规划解题方法论大曝光 &#xff01;详细信息还请看代码随想录讲解视频 文章目录 动态规划的常见类型动态规划的误区动规五步曲DP数组以及下标的含义递推公式DP数组如何初始化DP数组遍历顺序打印DP数组…

GeoLite2 geoip数据库下载和使用

GeoLite2 数据库是免费的 IP 地理定位数据库&#xff0c;与MaxMind 的 GeoIP2 数据库相当&#xff0c;但准确度较低 。GeoLite2 国家、城市和 ASN 数据库 每周更新两次&#xff0c;即每周二和周五。GeoLite2 数据还可作为 GeoLite2 Country 和 GeoLite2 City Web 服务中的 Web …

Kotlin 中的类和构造方法

Kotlin 中的类与接口和 Java 中的类与接口还是有区别的。例如&#xff0c;Koltin 中的接口可以包含属性声明&#xff0c;与 Java 不同的是。Kotlin 的声明默认是 final 和 public 的。此外&#xff0c;嵌套的类默认并不是内部类&#xff1a;它们并没有包含对其它外部类的隐式引…

实施阶段(2024年3月)

【项目活动1】需求分析 学生&#xff1a;在系统中可以账号登陆&#xff0c;查看今日菜谱&#xff0c;点餐反馈。 食堂管理人员&#xff1a;对原始数据整合&#xff0c;显示菜品结果统计&#xff0c;并根据统计结果对菜品供应量进行调整反馈&#xff0c;避免浪费。 【项目活动…

MySQL开窗函数

测试环境&#xff1a;mysql8.0.18 官方文档&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/window-functions.html 一、窗口函数介绍二、语法结构三、自定义窗口1.rows&#xff08;重点&#xff09;2.range3.默认窗口 四、常用窗口函数示例1.row_number & rank &…

C++之红黑树插入+查找功能实例(二百六十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

SeaTunnel 与 DataX 、Sqoop、Flume、Flink CDC 对比

产品概述 Apache SeaTunnel 是一个非常易用的超高性能分布式数据集成产品&#xff0c;支持海量数据的离线及实时同步。每天可稳定高效同步万亿级数据&#xff0c;已应用于数百家企业生产&#xff0c;也是首个由国人主导贡献到 Apache 基金会的数据集成顶级项目。 SeaTunnel 主…

当代深度学习模型介绍--循环神经网络(RNNs)

AI大模型学习 方向一&#xff1a;AI大模型学习的理论基础 模型和应用的多样化&#xff1a;随着研究的深入&#xff0c;深度学习领域出现了多种创新的模型架构&#xff1a; 卷积神经网络&#xff08;CNNs&#xff09;专门针对图像处理任务进行了优化&#xff0c;通过模拟生物视…

『Apisix系列』破局传统架构:探索新一代微服务体系下的API管理新范式与最佳实践

文章目录 『Apisix基石篇』『Apisix入门篇』『Apisix进阶篇』『Apisix安全篇』 『Apisix基石篇』 &#x1f680; 手把手教你从零部署APISIX高性能API网关 利用Docker-compose快速部署Apache APISIX及其依赖组件&#xff0c;实现高效的API网关搭建通过编写RPM安装脚本来自动化安…

IDEA MyBatisCodeHelper Pro最新版(持续更新)

目录 0. 你想要的0.1 包下载0.2 使用jh 1. 功能介绍2. 下载安装2.1 在idea中插件市场安装2.2 在jetbrains插件市场下载安装 3. 简单使用3.1 创建一个SpringBoot项目3.2 配置数据库3.3 一键生成实体类、mapper 0. 你想要的 0.1 包下载 测试系统&#xff1a;Windows&#xff08…

ERP与MES系统深度对接详细解决方案

此方案适合绝大部分生产型企业&#xff0c;企业如果有用到ERP&#xff0c;MES&#xff0c;WMS等其他系统的。可以借鉴以下的对接方案。 在ERP与MES系统对接的具体内容中&#xff0c;物料管理、出入库信息、物料清单&#xff08;BOM&#xff09;、生产计划、生产领料、生产用料的…

【吊打面试官系列】Redis篇 -Redis 回收进程如何工作的?

大家好&#xff0c;我是锋哥。今天分享关于 【Redis 回收进程如何工作的&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; ​Redis 回收进程如何工作的&#xff1f; 一个客户端运行了新的命令&#xff0c;添加了新的数据。Redi 检查内存使用情况&#xff0c;如 果…

浅析AI大模型当前存在的技术瓶颈和限制及解决方案

方向五&#xff1a;未来发展趋势与挑战 提示&#xff1a;展望AI大模型学习的未来发展趋势&#xff0c;并讨论当前面临的主要挑战。可以关注新技术、新方法的出现&#xff0c;以及它们对AI大模型学习的影响&#xff1b;同时&#xff0c;也可以分析当前存在的技术瓶颈和限制&…

P2802 回家

P2802 回家 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 虽然是普及-难度的题&#xff0c;但是感觉细节有很多。 细节&#xff1a; bfs第一次到 ( i , j ) (i, j) (i,j)&#xff0c;但是距离不一定是最小的 鼠标是一次性物品 血量到达 ( x x , y y ) (xx, yy) (xx,yy)为…

【文献分享】 机器学习 + 分子动力学 + 第一性原理计算 + 热力学性质(熔化温度 热导率 热膨胀系数)

分享一篇关于机器学习 分子动力学 第一性原理 熔化温度&#xff08;熔化温度 & 热导率 & 热膨胀系数&#xff09;的文章。 感谢论文的原作者&#xff01; 关键词&#xff1a; 1. Al−Li alloy 2. Neural network potential 3. Molecular dynamics 4. Thermal pr…

wireshark 使用

wireshark介绍 wireshak可以抓取经过主机网卡的所有数据包&#xff08;包括虚拟机使用的虚拟网卡的数据包&#xff09;。 环境安装 安装wireshark: https://blog.csdn.net/Eoning/article/details/132141665 安装网络助手工具&#xff1a;https://soft.3dmgame.com/down/213…

源支付V7开源版2.99,修复各种提示错误

源支付V7开源版2.99&#xff0c;修复各种提示错误 加密说明&#xff1a;200拿来的&#xff0c;只有8.1这个文件加密&#xff0c;其他文件无任何加密&#xff0c;已修复各种提示错误 测试其他开源版安装提示错误&#xff0c;有几个文件是加密的 注&#xff1a;开发不易&#…

AJAX(二):axios 和 fetch函数发送AJAX请求、同源策略、 jsonp、CORS

一、各种发送AJAX请求 jquery基于回调函数&#xff0c;axios基于promise 1.axios发送AJAX请求!!! axios (v1.5.0) - Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 Node.js 中。 | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务 服务器&#xff1a; app.…