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

一、前言

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

二、链表查询以及遍历

①获得链表的第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.rhkb.cn/news/139220.html

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

相关文章

Java多线程篇(4)——wait/notify和park/unPark

文章目录 Object - wait/notifyobject.wait()object.notify() LockSupport - park/unparkLockSupport.park()LockSupport.unPark() Object - wait/notify object.wait() ObjectSynchronizer::wait 从这段代码可以得到两个信息 1&#xff1a;wait() 底层是对象锁&#xff08;就…

《C++ primer》练习6.36-6.38:书写返回数组引用的函数声明

最近看C primer&#xff0c;看到《C primer》6.3.3练习&#xff0c;要求书写返回数组引用的函数声明&#xff0c;觉得有必要实践记录一下。 这里先总结返回数组的引用的的函数声明写法&#xff08;下面的Type是数组元素的类型&#xff0c;可以是int、float等&#xff0c;如果要…

ICCV 2023 | MPI-Flow:从单视角构建的多平面图像中学习光流

ICCV 2023 | MPI-Flow&#xff1a;从单视角构建的多平面图像中学习光流 引言&#xff1a;主要贡献&#xff1a;Motivation&#xff1a;算法细节&#xff1a;Optical Flow Data GenerationIndependent Object MotionsDepth-Aware Inpainting 实验结果&#xff1a; 来源&#xff…

2023年前端流行什么技术和框架了?

Web前端三大主流框架有React、Vue.js和Angular&#xff0c;由于接触过Vue.js&#xff0c;接下来主讲最新的Vue3.0&#xff01; Vue3.0作为最新版本的Vue.js框架&#xff0c;拥有更强大的性能和更丰富的功能&#xff0c;为低代码开发平台注入了全新的活力。而JNPF快速开发平台作…

Linux新手教程||Linux vi/vim

所有的 Unix Like 系统都会内建 vi 文书编辑器&#xff0c;其他的文书编辑器则不一定会存在。 但是目前我们使用比较多的是 vim 编辑器。 vim 具有程序编辑的能力&#xff0c;可以主动的以字体颜色辨别语法的正确性&#xff0c;方便程序设计。 什么是 vim&#xff1f; Vim是…

Chrome浏览器删除网站cookies的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

3.wifi开发,网络编程

网络协议栈LwIP WiFi UDP Clinet编程 WiFi UDP Server编程 WiFi TCP Client编程 WiFi TCP Server编程 一。LWIP原理介绍&#xff0c;API介绍&#xff0c;文件结构 1.Lwip支持的协议 2.API 3.文件结构 1.api目录&#xff1a;应用程序接口文件。 2.arch目录&#xff1a;与硬件和…

登录业务实现

登录业务实现&#xff1a; 登录成功/失败实现 -> pinia管理用户数据及数据持久化 -> 不同登录状态的模板适配 -> 请求拦截器携带token -> 退出登录实现 -> token失效&#xff08;401响应拦截&#xff09; 1. 登录成功/失败实现 当表单校验通过时&a…

iOS线上闪退问题解决方案

iOS线上闪退问题的收集工具是关键&#xff0c;它们可以帮助你及时发现和解决应用程序中的崩溃问题。以下是一些常用的iOS线上闪退问题收集工具及其使用方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合…

一招解除csdn复制限制

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

Google拟放弃博通自行研发AI芯片 | 百能云芯

谷歌计划自行研发人工智能&#xff08;AI&#xff09;芯片&#xff0c;考虑将博通&#xff08;Broadcom&#xff09;从其供应商名单中剔除&#xff0c;但谷歌强调双方的合作关系不会受到影响。 根据美国网络媒体《The Information》的报道&#xff0c;谷歌高层正在讨论可能在20…

VisualStudio配置opencv

下载opencv 链接&#xff1a;https://opencv.org/releases/ 我下载的是4.7.0&#xff0c;选择windows下载。 下载成功后打开exe文件&#xff0c;选择路径安装。 配置环境变量 安装成功后找到安装目录&#xff0c;复制bin目录路径。 我的是放在了D盘 D:\Opencv4.7.0\opencv…

uni-app, 实现 scroll-view 自动滚动到底部,并控制触发频率

实现思路 通过 scroll-view 组件的 scroll-top 属性可以设置容器竖向滚动条位置 属性名Valuescroll-y允许纵向滚动scroll-top设置竖向滚动条位置 想要实现 scroll-view 滚动到底部&#xff0c;只需要让 scroll-top scroll-view 内容高度 - scroll-view 容器本身高度&#…

黑马JVM总结(十九)

&#xff08;1&#xff09;GC调优1 通过官网查看查看JVM的参数&#xff1a; 可以使用java命令查看当前环境下的虚拟机参数&#xff1a; 学会使用一些工具如前面学的jmap &#xff0c;jconsole等等工具 &#xff08;2&#xff09;GC调优2 垃圾回收调优只是众多调优中的一个方…

聊聊wireshark的进阶使用功能 | 京东云技术团队

1. 前言 emmm&#xff0c;说起网络知识学习肯定离不来wireshark工具&#xff0c;这个工具能够帮助我们快速地定位网络问题以及帮助正在学习网络协议这块的知识的同学验证理论与实际的一大利器&#xff0c;平时更多的只是停留在初步的使用阶段。也是利用部门内部的网络兴趣小组…

关于分布式一致性

一致性&#xff08;consistency&#xff09; 说到一致性&#xff0c;我们可能最先想到的数据库里的事务 这里的讨论的是分布式的一致性&#xff0c;事务就简化一下&#xff0c;只考虑Read/Write 先列举一下事务的种类&#xff1a; 单机的事务&#xff1a;多个复杂事务发生在一…

【异常报错】must call Vue.use(Vuex)

这个错误应该是在创建Vuex中出现的 把你main.js中的Vue.use(Vuex)写到store中&#xff0c;这里我的store/index.js中,即完美解决 其实仔细想想也可以发现&#xff0c;import就把整个文件给引入了&#xff0c;而index.js中有创建Store的实例&#xff0c;而在这时我们还没有Vue.…

Redis集群架构搭建——主从、哨兵、集群

上一篇文章Ubuntu上通过源码方式安装Redis已经介绍了如何安装redis&#xff0c;在这篇文章中&#xff0c;将会教大家搭建Redis的几种高可用的架构&#xff1a;主从架构、哨兵集群、Cluster集群。 本篇文章使用的redis版本为6.2.13&#xff0c;不同版本的配置可能有略微的区别&a…

腾讯云微服务平台 TSF 异地多活单元化能力重磅升级

导语 2023腾讯全球数字生态大会已于9月7-8日完美落幕&#xff0c;40专场活动展示了腾讯最新的前沿技术、核心产品、解决方案。 微服务与消息队列专场&#xff0c;腾讯云微服务平台 TSF 产品经理张桢带来了《腾讯云微服务平台 TSF 异地多活单元化能力重磅升级》的精彩演讲。本…

Centos7部署单机版MongoDB

目录 Centos7部署单机版MongoDBMongoDB介绍数据模型索引分布式高可用性查询语言驱动和社区用途缺点 下载并解压安装包创建相关文件夹和文件编辑mongod.conf文件启动mongodb创建管理员用户终止MongoDB服务配置自启动服务关闭SELinux编辑自启动服务文件mongodb服务命令 Centos7部…