Java数据结构篇——单链表的基本操作

1. 前言

在上一篇《Java数据结构篇——实现顺序表的增删查改》,我们已经熟悉了 ArrayList 的使用并且进行了简单的模拟实现。ArrayList底层使用数组来存储元素,由于其底层是一段连续的空间,当ArrayList 任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后移动,时间复杂度为O(n),效率比较低,因此ArrayList 不适合做任意位置插入和删除比较多的场景。因此:Java集合这种又引入了 LinkedList,即链表结构。

2. 链表

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

image-20231216144405243

注意:

  1. 从上图可看出,链表结构正在逻辑上是连续的,但是在物理上(内存)不一定连续。
  2. 现实中的节点一般都是从堆上申请出来的。
  3. 从堆上申请的空间,是按照一定的额策略来分配的,两次申请的空间可能连续,也可能不连续。

3. 单链表的实现

创建一个链表

public class MySingleList {// 节点static class ListNode {public int val; // 数值域 - 存放当前节点的值public ListNode next; // next域 指向下一个节点public ListNode(int val) {this.val = val;}}// 链表的属性 链表的头节点public ListNode head; // nullpublic void createList() {ListNode node1 = new ListNode(1);ListNode node2 = new ListNode(2);ListNode node3 = new ListNode(3);ListNode node4 = new ListNode(4);node1.next = node2;node2.next = node3;node3.next = node4;this.head = node1;}
}

画图表示:

image-20231216155247814

3.1 打印链表

  1. 怎么从第一个节点走到第二个节点?

    答:head = head.next

  2. 什么时候算是把节点都遍历完成?

    答: head == null

代码实现:

	/**** 打印链表*/@Overridepublic void display() {ListNode cur = head;while (cur != null) {System.out.print(cur.val + " ");cur = cur.next;// 让cur这个节点 可以从一个节点走到下一个节点}System.out.println();}

3.2 头插法

在链表的第一个位置插入元素。

思路:

  1. 插入元素的next指向head
  2. head指向插入元素

image-20231216163615979

代码实现:

    /*** 头插法* @param data*/@Overridepublic void addFirst(int data) {ListNode node = new ListNode(data); // 定义一个节点node.next = head;head = node;}

3.3 尾插法

在链表的最后个位置插入元素

思路:

  1. 判断链表中是否有元素。
  2. 如果没有元素,直接添加头结点即可。
  3. 如果有元素,将原链表最后一个元素next指向插入的元素。

image-20231216165016370

代码实现:

	/*** 尾插法* @param data*/@Overridepublic void addLast(int data) {ListNode node = new ListNode(data); // 定义一个节点if (head == null) { // 链表一个元素都没有head = node;} else {ListNode cur = head;while (cur.next != null) {cur = cur.next;}cur.next = node;}}

3.4 任意位置插入元素

思路:

  1. 判断index是否合法(index < 0 或者 index 大于链表长度),如果不合法则抛出异常。
  2. 判断index 等于0或者index等于链表长度,则使用头插法或尾插法
  3. cur找到index - 1位置
  4. 插入元素的next指向curnext
  5. curnext指向插入的元素

image-20231216180417677

代码实现:

    /*** 在index位置 插入data* @param index* @param data*/@Overridepublic void addIndex(int index, int data) throws IndexException{if (index < 0 || index > size()) {throw new IndexException("index不合法:" + index);}ListNode node = new ListNode(data); // 定义一个节点if (head == null) {head = node;return;}if (index == 0) {addFirst(data);return;}if (index == size()) {addLast(data);return;}ListNode cur = searchPrevIndex(index);node.next = cur.next;cur.next = node;}/*** 找到index-1的位置* @param index* @return*/private ListNode searchPrevIndex(int index) {ListNode cur = head;int count = 0;while (count != index - 1) {cur = cur.next;count++;}return cur;}

异常类:

public class IndexException extends RuntimeException{public IndexException() {}public IndexException(String msg) {super(msg);}
}

3.5 查找元素

代码实现:

    /**** 求当前链表 是否存在key* @param key* @return*/@Overridepublic boolean contains(int key) {ListNode cur = head;while (cur != null) {if (cur.val == key) {return true;}cur = cur.next;}return false;}

3.6 链表节点个数

代码实现:

	/*** 求当前链表 有多少个节点* @return*/@Overridepublic int size() {ListNode cur = head;int count = 0;while (cur != null) {count++;cur = cur.next;}return count;}

3.7 删除元素

思路:

  1. 判断链表是否为空,如果为空直接返回
  2. 判断删除元素是否为头节点,如果是则head指向headnext
  3. 定义指针找到要删除节点的前一个节点
  4. 前一个节点的next指向删除节点的next

image-20231216183736354

代码实现:

    /**** @param key*/@Overridepublic void remove(int key) {if (head == null) {return;}if (head.val == key) {head = head.next;return;}ListNode cur = findPrevKey(key);if (cur == null) {return;// 链表里要没有删除的数字}ListNode del = cur.next;cur.next = del.next;}/*** 找到删除节点的前一个节点* @param key* @return*/private ListNode findPrevKey(int key) {ListNode cur = head;while (cur.next != null) {if (cur.next.val == key) {return cur;} else {cur = cur.next;}}return null;}

3.8 [删除链表中指定的所有元素](203. 移除链表元素 - 力扣(LeetCode))

思路:

  1. 判断链表是否为空,如果是空直接返回
  2. 定义指针cur:可能要删除的节点
  3. 定义指针prev:可能要删除的节点的前驱
  4. 判断curval是不是要删除的元素,如果是prevnext指向curnextcur指向curnext;否则prev指向curcur指向curnext
  5. 判断头节点的val是否为的元素,如果是头节点指向头节点的neext

image-20231216210941437

代码实现:

    /*** 删除链表中所有的key* @param 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;}}

LeetCode运行结果:

image-20231216213052758

3.9 清空链表

当一个对象,没有被引用的时候,就会被回收掉

    /*** 清空链表*/@Overridepublic void clear() {head = null;}

[4. 代码](MySingleList/src · 白日依山璟/JavaSE_code - 码云 - 开源中国 (gitee.com))

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

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

相关文章

《使用ThinkPHP6开发项目》 - 登录接口一

《使用ThinkPHP6开发项目》 - 安装ThinkPHP框架-CSDN博客 《使用ThinkPHP6开发项目》 - 设置项目环境变量-CSDN博客 《使用ThinkPHP6开发项目》 - 项目使用多应用开发-CSDN博客 《使用ThinkPHP6开发项目》 - 创建应用-CSDN博客 《使用ThinkPHP6开发项目》 - 创建控制器-CSD…

详解Keras3.0 Layers API: Convolution layers(Conv1D、Conv2D、Conv3D)

1、Conv1D layer 通常对一维度数组&#xff08;例&#xff1a;arr np.array([1, 2, 3, 4, 5])&#xff09;进行卷积操作 keras.layers.Conv1D(filters,kernel_size,strides1,padding"valid",data_formatNone,dilation_rate1,groups1,activationNone,use_biasTrue,…

职场记6:在国企工作,追逐挑战与成就

上一篇《职场记5&#xff1a;勇闯深圳&#xff0c;追梦职场》 上回说到我决定入职一家国企&#xff0c;去入职后才发现&#xff0c;我应聘的岗位其实只招一人&#xff0c;加上我却一共来了两个人&#xff0c;也就是说我和另一个新人最终要有一个离开。 尽管我和他有着一定的竞…

SystemVerilog基础:并行块fork-join、join_any、join_none(二)

相关阅读 SystemVerilog基础https://blog.csdn.net/weixin_45791458/category_12517449.html 在第一节中&#xff0c;我们讨论了并行块中的fork-join块和fork-join_any块&#xff0c;了解了它们的差异&#xff0c;本文将继续讨论fork-join_none块的使用。 fork-join_none并行块…

12.12_黑马数据结构与算法笔记Java

目录 079 优先级队列 无序数组实现 080 优先级队列 有序数组实现 081 优先级队列 堆实现 1 082 优先级队列 堆实现 2 083 优先级队列 堆实现 3 084 优先级队列 e01 合并多个有序链表1 084 优先级队列 e01 合并多个有序链表2 085 阻塞队列 问题提出 086 阻塞队列 单锁实…

5个创建在线帮助文档的好方法!

在线帮助文档是企业为用户提供支持服务的重要工具&#xff0c;它能够帮助用户更好地了解和使用产品&#xff0c;提高用户体验。然而&#xff0c;创建一份优秀的在线帮助文档需要掌握一定的技巧和方法。接下来就介绍一下创建在线帮助文档的5个好方法&#xff0c;帮助企业更好地为…

Linux: network:tcp: option: TCP_INFO

https://www.man7.org/linux/man-pages/man7/tcp.7.html https://www.man7.org/linux/man-pages/man8/ss.8.html 从TCP的使用手册上看,这个选项的作用是返回一个结构体数据。2.4 就引入了,其实大家可以用起来这个选项。 TCP_INFO (since Linux 2.4) Used to collect informa…

【JavaWeb学习笔记】10 - 手写Tomcat底层,Maven的初步使用

一、Maven 1.Maven示意图 类似Java访问数据库 2.创建Maven案例演示 配置阿里镜像 找到setting目录 但一开始配置不存在该文件 需要去Maven主目录下的conf拿到settings拷贝到上述目录 拷贝到admin/.m2后打开该settings 在<mirrors>内输入镜像地址 <mirror> …

C语言—每日选择题—Day52

第一题 1. 执行c程序代码&#xff0c;a,b,c,d的值分别为&#xff08;&#xff09; int a 1; int b 0; int c 0; int d (a) * (c 1); A&#xff1a;2&#xff0c;0&#xff0c;1&#xff0c;2 B&#xff1a;1&#xff0c;0&#xff0c;1&#xff0c;1 C&#xff1a;2&…

Docker--Docker镜像仓库

一、搭建私有镜像仓库 搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。 官网地址&#xff1a;https://hub.docker.com/_/registry &#xff08;一&#xff09;简化版镜像仓库 Docker官方的Docker Registry是一个基础版本的Docker镜像仓库&#xff0c;具备仓库…

线下实体门店引流,百万私域电商高手都在用的实战营销引流技巧!

线下实体门店引流&#xff0c;百万私域电商高手都在用的实战营销引流技巧&#xff01; 无论是初创公司还是已经在步入正轨的实体门店&#xff0c;有个现实的实例告诉你&#xff1a;互联网上90%的引流技巧告诉你的方法&#xff0c;其实都是不挣钱的&#xff0c;辛辛苦苦折腾一整…

大数据技术之Shell(超级详细)

大数据技术之Shell&#xff08;超级详细&#xff09; 第1章 Shell概述 Shell 是一种脚本语言&#xff0c;用于在操作系统的命令行界面&#xff08;CLI&#xff09;下执行命令和脚本。在大数据领域&#xff0c;Shell 脚本常用于编写数据处理和分析任务的自动化脚本&#xff0c…

Redis设计与实现之对象处理机制

目录 一、前言 二、对象处理机制 1、redisObject 数据结构&#xff0c;以及 Redis 的数据类型 2、 命令的类型检查和多态 3、对象共享 4、引用计数以及对象的销毁 三、对象的处理 1、Redis是如何处理字符串对象的&#xff1f; 2、Redis是如何处理列表对象的&#xff1f…

使用Selenium与Scrapy处理动态加载网页内容的解决方法

博客正文&#xff08;包含详细注释&#xff09; 引言 在爬虫技术领域&#xff0c;处理动态加载的网页内容常常是一项挑战&#xff0c;尤其是对于那些通过用户滚动或其他交互动态加载更多内容的网站。本文将介绍如何结合使用Selenium和Scrapy来有效处理这类网页。 初探Seleni…

十九)Stable Diffusion使用教程:ai室内设计案例

今天我们聊聊如何通过SD进行室内设计装修。 方式一:controlnet的seg模型 基础起手式: 选择常用算法,抽卡: 抽到喜欢的图片之后,拖到controlnet里: 选择seg的ade20k预处理器,点击爆炸按钮,得到seg语义分割图,下载下来: 根据语义分割表里的颜色值,到PS里进行修改: 语…

制作一个简单 的maven plugin

流程 首先&#xff0c; 你需要创建一个Maven项目&#xff0c;推荐用idea 创建项目 会自动配置插件 pom.xml文件中添加以下配置&#xff1a; <project> <!-- 项目的基本信息 --> <groupId>com.example</groupId> <artifactId>my-maven-plugi…

封装调用的js方法

// 防止处理多次点击 function noMultipleClicks(methods, info) { // methods是需要点击后需要执行的函数&#xff0c; info是点击需要传的参数 let that this; if (that.noClick) { // 第一次点击 that.noClick false; if (info &…

深入理解JVM设计的精髓与独特之处

这是Java代码的执行过程 从软件工程的视角去深入拆解&#xff0c;无疑极具吸引力&#xff1a;首个阶段仅依赖于源高级语言的细微之处&#xff0c;而第二阶段则仅仅专注于目标机器语言的特质。 不可否认&#xff0c;在这两个编译阶段之间的衔接&#xff08;具体指明中间处理步…

javacv的视频截图功能

之前做了一个资源库的小项目&#xff0c;因为上传资源文件包含视频等附件&#xff0c;所以就需要时用到这个功能。通过对视频截图&#xff0c;然后作为封面缩略图&#xff0c;达到美观效果。 首先呢&#xff0c;需要准备相关的jar包&#xff0c;之前我用的是低版本的1.4.2&…

25个校招网络编程面试题

1、什么是IO多路复用 I/O多路复用的本质是使用select,poll或者epoll函数&#xff0c;挂起进程&#xff0c;当一个或者多个I/O事件发生之后&#xff0c;将控制返回给用户进程。以服务器编程为例&#xff0c;传统的多进程(多线程)并发模型&#xff0c;在处理用户连接时都是开启一…