数据结构与算法(六)--链表的遍历,查询和修改,删除操作

一、前言

上篇文章我们了解了链表的概念以及链表底层的搭建以及向链表中添加元素的操作。本次我们继续学习链表剩余的操作:遍历,查询和修改、删除操作。

二、链表查询以及遍历

①获得链表的第index(0-based)个位置的元素(不常用,仅做练习)

和add不一样的是,add我们是要找到第Index的前一个元素,所以,我们起点从dummyHead开始,然后遍历index次。而get不同,get就是要第Index上的元素,所以我们可以直接从dummyHead.next开始,其实就是"索引"为0的位置开始,遍历index次,这样就可以找到第Index个位置的元素了。

	//获取index索引上的元素public T get(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("get failed;index should >= 0 or index < size");}Node cur = dummyHead.next;for (int i = 0; i < index; i++) {cur = cur.next;}return cur.data;}

那么同理有了get(),我们就可以添加更方便的一些方法,例如getFirst()和getLast():

    public T getFirst(){return get(0);}public T getLast(){return get(size - 1);}

②、查找链表中是否有元素e

这个就有点特殊了,因为我们现在不知道具体要在哪个“索引”操作,所以我们需要从头开始遍历
那么我们可以使用for循环,和之前一样,从"索引"为0的位置开始找,然后遍历size次,这种方式是可行的。但是这里呢我们采用while循环来遍历链表,因为这种方式我们后面会用到很多,那么代码非常的简单,如下所示,这其实就是链表的遍历:

	public boolean contains(T t){Node cur = dummyHead.next;//只要cur不为NULL,其实就是到最后一个节点while (cur != null){if(cur.data == t){return true;}cur = cur.next;}return false;}

其实用for循环不使用size变量也是可以做到的,思路和上面的while循环大同小异:

for(Node cur = dummyHead.next; cur != null; cur = cur.next){...}

类似的,我们也可以在toString()中去遍历我们的链表:

	@Overridepublic String toString(){StringBuilder stringBuilder = new StringBuilder();Node cur = dummyHead.next;while (cur != null){stringBuilder.append(cur + "->");cur = cur.next;}stringBuilder.append("NULL");return stringBuilder.toString();}

三、链表的更新(不常用,仅做练习)

更新操作其实和上面的get操作非常类似,只是将返回元素变为了直接更新,这里不做赘述,代码如下:

	public void set(int index, T t){if (index < 0 || index >= size) {throw new IllegalArgumentException("get failed;index should >= 0 or index < size");}Node cur = dummyHead.next;for (int i = 0; i < index; i++) {cur = cur.next;}cur.data = t;}

四、链表元素的删除

那么有了之前的基础,我们删除元素是很简单的,我们仍然需要用到虚拟头结点。
例如,我想要删除"索引"为2位置上的元素:
在这里插入图片描述
那么对于删除链表元素来说,我们和添加元素是一样的,我们需要找到被删除元素的前一个元素,所以我们仍然需要prev,而prev.next就是我们要删除的节点delNode了:
在这里插入图片描述
然后 我们要做的就是将prev.next = delNode.next:,这样做完之后,我们链表顺着这个next走。1的next就是3,3的next就是4,从某种意义来说等同于将2这个节点删除了。
在这里插入图片描述
当然为了方便我们java回收这个空间,我们应该手动将2这个删除节点的next指向null,delNode.next =null;

然后我们便可以开始进行代码设计了,删除代码非常的简单:

	public T remove(int index){if (index < 0 || index >= size) {throw new IllegalArgumentException("get failed;index should >= 0 or index < size");}Node prev = dummyHead;for(int i = 0;i<index;i++){prev = prev.next;}Node ret = prev.next;prev.next = ret.next;ret.next = null;size --;return ret.data;}

那么remove完成后,我们同理可以设计一些方便的remove方法,即removeFirst,removeLast等:

	public T removeFirst(){return remove(0);}	public T removeLast(){return remove(size - 1);}

我们可以试试:

	public static void main(String[] args) {LinkedList<Integer> integerLinkedList = new LinkedList<>();for (int i = 0; i < 5; i++) {integerLinkedList.addFirst(i);System.out.println(integerLinkedList);}integerLinkedList.add(666,2);System.out.println(integerLinkedList);System.out.println(integerLinkedList.remove(2));System.out.println(integerLinkedList.removeLast());System.out.println(integerLinkedList);}

在这里插入图片描述
五、链表的时间复杂度分析

添加操作

  • addLast(e) ----------- O(n)
  • addFirst(e) ---------- O(1)
  • add(index,e) -----------O(n/2)=O(n)

所以综上来看,链表的添加操作是O(n)的

删除操作

  • removeLast(e) ----------- O(n)
  • removeFirst(e) ---------- O(1)
  • remove(index,e) -----------O(n/2)=O(n)

所以综上来看,链表的删除操作也是O(n)的

修改操作

  • set(index,e) -------O(n)

查找操作

  • get(index) ----------- O(n)
  • contains(e) ----------- O(n)

但是如果查询的是链表头元素的时候,此时时间复杂度是O(1)

所以综上来看,链表的查找操作也是O(n)的

那么综上分析,链表的CRUD操作时间复杂度全是O(n)的,确实在时间复杂度的角度上分析,它确实整体不如数组,因为数组具有随机访问的能力,但是链表底层上就不支持。但是我们发现如果只对链表头进行增删操作,时间复杂度均为O(1),所以我们的链表它适合做的事情是不去修改,而对于查也不能去查任意的元素,可以只查链表头的元素.并且在增加和删除的时候,只能对链表头进行操作。且链表本身就是动态的数据结构,是非常节省内存空间的。

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

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

相关文章

MySQL详细案例 1:MySQL主从复制与读写分离

文章目录 1. MySQL主从复制1.1 使用场景1.2 MySQL的复制类型1.3 主从复制的作用1.4 主从复制的工作过程1.5 实现MySQL主从复制1.5.1 前置准备1.5.2 主服务器mysql配置1.5.3 从服务器1 mysql配置1.5.4 从服务器2 mysql配置1.5.5 测试 1.6 主从复制的3种同步模式1.6.1 异步复制&a…

微信小程序底部安全区域高度获取

CSS 属性 safe-area-inset-bottom safe-area-inset-bottom 就是安全区的高度 padding-bottom:env(safe-area-inset-bottom); wx.getSystemInfoSync() wx.getSystemInfoSync()可以获取系统信息 let system wx.getSystemInfoSync() let bottomSafe system.screenHeight -…

一招解除csdn复制限制

先看这个代码 python读取英文pdf翻译成中文pdf文件导出代码 想要复制代码&#xff0c;csdn有限制怎么办&#xff08;csdn流氓&#xff0c;无耻&#xff09; 解除方法 ctrlu 看效果

Linux启动过程详解 Xmind导图笔记

参考大佬博客&#xff1a; 简要描述linux系统从开机到登陆界面的启动过程 Linux启动过程详解 Bootloader详解 来源&#xff1a;从BIOS开始画图了解Linux启动过程——老杨Linux

TSINGSEE视频AI智能分析技术:水泥厂安全生产智能监管解决方案

一、方案背景 随着人工智能技术的快速发展以及视频监控系统在全国范围内的迅速推进&#xff0c;基于AI视频智能分析技术的智能视频监控与智慧监管系统&#xff0c;也已经成为当前行业的发展趋势。在工业制造与工业生产领域&#xff0c;工厂对设备的巡检管理、维护维修、资产管…

【全志V3s】SPI NAND Flash 驱动开发

文章目录 一、硬件介绍V3s的启动顺序 二、驱动支持U-Boot驱动主线 Linux 驱动已经支持 三、烧录工具 xfel四、构建U-Boot&#xff08;官方的Uboot&#xff09;先编译一下开始spi nand flash 代码层面的适配修改menuconfig配置ARM architecture配置Support for SPI Nand Flash o…

rabbitMQ (1)

文章目录 1. RabbitMQ 介绍1.1 几个重要概念1.2 RabbitMq 的工作原理 2 RabbitMQ 安装3. RabbitMQ 入门操作3.1 添加依赖3.2 生产者代码3.3 消费者代码 4. Work Queues5. 管理端页面创建队列 1. RabbitMQ 介绍 引用 &#xff1a; RabbitMQ 是一个消息中间件&#xff1a;它接受…

Xilinx FPGA 程序固化重新上电程序不运行的问题

问题描述 FPGA直接下载bit文件,功能正常。 FPGA擦除FLASH,烧写FLASH,正常。 电源断电,重新上电,FALSH里面的程序没有启动,FPGA程序没有跑起来。–FLASH启动不正常。 解决办法 在XDC约束文件里边增加约束: ## Configuration options, can be used for all designs se…

[Linux入门]---Linux项目自动化构建工具-make/Makefile

目录 1.背景2.make指令输入make默认为Makefile文件第一条指令执行Makefile文件对gcc指令特殊处理及原理特殊符号 3.总结 1.背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放…

CNN(九):Inception v3算法实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 1 理论基础 Inception v3论文 Inception v3由谷歌研究员Christian Szegedy等人在2015年的论文《Rethinking the Inception Architecture f…

Jmeter集成到jenkins

Jmeter集成到Jenkins Jmeter集成到Jenkins. 1 软件下载... 4 一:环境配置... 4 1.JDK安装&#xff1a;... 4 配置JDK环境变量... 5 2.Jmeter安装&#xff1a;... 5 配置jmeter环境变量... 6 3.安装Ant 7 配置Ant环境变量... 7 4.Git安装&#xff1a;... 8 配置git环境…

Untiy UDP局域网 异步发送图片

同步画面有问题&#xff0c;传图片吧 using System.Text; using System.Net.Sockets; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using System.Net; using System; using System.Threading.Tasks; using Sy…

java内嵌浏览器CEF-JAVA、jcef、java chrome

java内嵌浏览器CEF-JAVA、jcef、java chrome jcef是老牌cef的chrome内嵌方案&#xff0c;可以进行java-chrome-h5-桌面开发&#xff0c;下面为最新版本&#xff08;2023年9月22日10:33:07&#xff09; JCEF&#xff08;Java Chromium Embedded Framework&#xff09;是一个基于…

Cesium 空间量算——生成点位坐标

文章目录 需求分析1. 点击坐标点实现2. 输入坐标实现 需求 用 Cesium 生成点位坐标&#xff0c;并明显标识 分析 以下是我的两种实现方式 第一种是坐标点击实现 第二种是输入坐标实现 1. 点击坐标点实现 //点位坐标getLocation() {this.hoverIndex 0;let that this;this.view…

板子接线图

1.ST-LINK V2接线 2.对抗板子刷蓝牙固件 接USB转TTL&#xff0c;用镊子短接两个孔 2.对抗板子用串口测试蓝牙AT命令 短接白色箭头&#xff0c;接TX&#xff0c;RX&#xff0c;电源

MongoDB【部署 04】Windows系统实现MongoDB多磁盘存储

Windows系统实现多磁盘存储 1.为什么2.多磁盘存储2.1 数据库配置2.2 文件夹磁盘映射2.3 创建新的数据集 3.总结 1.为什么 这里仅针对只有一台Windows系统服务器的情景&#xff1a; 当服务器存储不足时&#xff0c;或者要接入更多的数据&#xff0c;就会挂载新磁盘&#xff0c…

边缘计算AI智能安防监控视频平台车辆违停算法详解与应用

随着城市车辆保有量呈现高速增长趋势&#xff0c;交通拥堵、违章行为也日益泛滥。因为车辆未停放在指定区域导致的车位浪费、占用/堵塞交通要道、车辆剐蹭等问题层出不穷。通过人工进行违法停车的监控&#xff0c;不仅让监控人员工作负荷越来越大&#xff0c;而且存在发现不及时…

Lua学习笔记:词法分析

前言 本篇在讲什么 Lua的词法分析 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题…

SpringAOP补充-通知获取类型

JoinPoint 是 ProceedingJoinPoint 的父类。 getArgs()是JoinPoint获取原方法返回值的函数。 preceed()是ProceedingJoinPoint获取原方法返回值的函数。

【Java】Servlet API

Servlet API HttpServlet核心方法Servlet生命周期 HttpServletRequest核心方法 HttpServletResponse核心方法 HttpServlet 我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其中的某些方法. 核心方法 方法名称调用时机init在 HttpServlet 实…