Java链表(1)

🐵本篇文章将对单链表进行讲解,模拟实现单链表中常见的方法


一、什么是链表

链表是一种逻辑结构上连续而物理结构上不一定连续的线性表,链表由一个一个节点组成:

每一个节点中都由数据域(val)和指针域(next)组成,数据域用于存放要存放在该节点的数据,指针域用于存放节点的地址,上图中链表的每一个节点的指针域存放的是下一个节点的地址,最后一个节点的指针指向空

二、链表的种类

链表细分可以分为八种,分别为:

1. 单向不带头非循环链表 2. 单向不带头循环链表 

3. 单向带头非循环链表     4. 单向带头循环链表

5. 双向不带头非循环链表 6. 双向不带头循环链表 

7. 单向带头非循环链表     8. 双向带头循环链表

三、链表的模拟实现

首先对第一种单链表的增删查改等操作用Java进行模拟实现,先将要模拟实现的方法写到IList接口中:

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

之后再创建一个MySingleList类实现上述接口并重写接口中所有的方法

public class MySingleList implements IList{static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head; //指向第一个节点/*以下是要重写IList接口中的方法*/...}

在MySingleList类中创建一个静态内部类ListNode用于描述一个节点对象,val用于存放数据,next用于存放下一个节点的地址,构造方法用于初始化数据va,接下来对上述方法进行模拟实现

3.1 方法的实现

public void addFirst(int data);

在链表的头部新增一个节点newNode

很明显要在头部新增一个节点就应让newNode的next指向head,并让newNode成为head

    public void addFirst(int data) {ListNode newNode = new ListNode(data);newNode.next = head;head = newNode;}

public void addLast(int data);

在链表的尾部新增一个节点

应让最后一个节点的next引用指向newNode,链表无法像顺序表一样可以直接找到某个位置的节点,所以应该通过循环先找到最后一个节点:

ListNode cur = head; //通常一个链表的头指针不动,需要定义一个cur来遍历链表、while (cur.next != null) {cur = cur.next; //只要cur的next不是空,cur就指向下一个节点
}//循环完成后cur就是最后一个节点
cur.next = newNode; 

完成以上操作后还要考虑一个特殊情况:如果链表为空,上述代码能否完成尾插操作?答案是不能的,因为如果链表为空,则head为空,cur为空,在循环条件处cur.next != null就会抛出一个NullPointerException的空指针异常,所以要单独处理链表为空的情况:

    public void addLast(int data) {ListNode newNode = new ListNode(data);if (head == null) { //如果链表为空,则直接让head指向newNodehead = newNode;} else {ListNode cur = head;while (cur.next != null) {cur = cur.next;}cur.next = newNode;}}

public int size();

求链表的长度也就是该链表有几个节点,只要直接遍历链表即可

    public int size() {ListNode cur = head;int count = 0;while(cur != null) { //注意这里和尾插的循环条件不一样count++;cur = cur.next;}return count;}

public boolean contains(int key);

判断链表中是否有节点的val值等于key,也是只要直接遍历链表即可

    public boolean contains(int key) {ListNode cur = head;while(cur != null) {if (cur.val == key) {return true;}cur = cur.next;}return false;}

public void addIndex(int index,int data);

在任意位置处插入一个节点,第一个节点的索引为0

首先要判断一下index是否合法:

public class IndexException extends RuntimeException{public IndexException(String message) {super(message);}
}=======================================================public void addIndex(int index, int data) {if (index < 0 || index > size()) {throw new IndexException("下标错误");}...
}

在任意位置插入节点,所以如果index为0或等于链表长度,就可以直接使用刚刚实现过的头插和尾插方法

public void addIndex(int index, int data) {if (index < 0 || index > size()) {throw new IndexException("下标错误");}if (index == 0) {addFirst(data);}if (index == size()) {addLast(data);}...
}

然后就是一般情况下:

如果要在1位置处插入新节点,那就应该先找到1位置处的节点的前驱节点,这里定义为cur,令newNode.next = cur.next;这样newNode的next就指向1位置处的节点,之后令cur.next = newNode这样就插入完成了

    public void addIndex(int index, int data) {if (index < 0 || index > size()) {throw new IndexException("下标错误");}if (index == 0) {addFirst(data);}if (index == size()) {addLast(data);}ListNode newNode = new ListNode(data);ListNode cur = head;for (int i = 0; i < index - 1; i++) { 找到插入节点的前驱节点cur = cur.next;}newNode.next = cur.next;cur.next = newNode;}

public void remove(int key);

假如要删除val = 20的节点(这里先定义为del)如果要删除该节点就应让del的前驱节点的next指向del的后继节点:

    public void remove(int key) {ListNode cur = head;while(cur.next.val != key) { //通过循环找到del的前驱节点cur = cur.next; }cur.next = cur.next.next;}

写完后还要考虑两种特殊情况:

第一,如果链表为空,上述代码不能满足要求,因为在循环条件处会抛出空指针异常

第二,如果要删除的节点是第一个节点,上述代码也不能满足要求,因为该循环是从第一个节点的下一个节点开始判断的

以上两种情况都需要单独处理:

    public void remove(int key) {if (head == null) {return;}if (head.val == key) {head = head.next;return;}ListNode cur = head;while(cur.next.val != key) {cur = cur.next;}cur.next = cur.next.next;}

public void removeAllKey(int key);

删除所有val = key的节点,那就需要遍历整个链表,在遍历过程中删除节点:

    public void removeAllKey(int key) {ListNode cur = head;while (cur.next != null) {if(cur.next.val == key) {cur.next = cur.next.next;} else {cur = cur.next;}}}

在循环的结束也要判断一下第一个节点是否为要删除的节点,因为上述循环条件为cur.next != null没有判断第一个节点:

    public void removeAllKey(int key) {if (head == null) { //如果链表为空则直接返回return;}ListNode cur = head;while (cur.next != null) {if(cur.next.val == key) {cur.next = cur.next.next;} else {cur = cur.next;}}if (head.val == key) {head = head.next;}}

public void clear();

清空链表,由于对象在没有被引用时,就会自动被回收,所以只需要将head置为空就行了

public void clear() {head = null;
}

🙉本篇文章到此结束,下篇文章将对LinkedList类进行讲解

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

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

相关文章

实战EDA电子设计自动化经典入门模型VHDL代码编写(含代码解释)上篇--状态机,逻辑设计:Y=AB+C

前言 电子设计自动化&#xff08;EDA&#xff09;&#xff1a; 定义&#xff1a;EDA是用于设计和开发复杂的电子系统&#xff08;如集成电路&#xff09;和印刷电路板的软件工具集合。这些工具通常用于设计电路、进行仿真测试、分析电路行为以及协助制造过程。应用&#xff1a;…

机器人学论文——智能施药机器人调研报告

目录 摘 要 Abstract 第一章&#xff1a;引言 1.1研究背景 1.2 研究意义 1.3文章架构 第二章&#xff1a;智能施药机器人发展现状 2.1引言 2.2 大田智能施药机器人发展现状 2.3 果园智能施药机器人发展现状 2.4 设施农业智能施药机器人发展现状 第三章&#xff1a;智能施药机器…

docker指令存档

目录 Docker 1、概念 2、架构图 3、安装 4、Docker怎么工作的&#xff1f; 5、Docker常用命令 帮助命令 镜像命令 1、查看镜像 2、帮助命令 3、搜索镜像 4、拉取镜像 5、删除镜像 容器命令 1、启动 2、查看运行的容器 3、删除容器 4、启动&停止 其他命令…

大数据数据流分析和处理的工具pig,从入门到精通!

介绍&#xff1a;Pig是一种数据流语言和运行环境&#xff0c;用于处理和分析大数据。 Pig由两个主要部分构成&#xff1a; Pig Latin语言&#xff1a;这是一种用于描述数据流的高级语言&#xff0c;它允许用户以较为简洁的方式编写数据处理和转换任务。 Pig执行环境&#xff1a…

C++ 模拟实现mapset

目录 一、改造红黑树 1、模板T改造节点 2、提取节点中的key 3、迭代器类 operator operator-- 4、改造insert 5、红黑树迭代器 6、 普通迭代器构造const迭代器 二、set 三、map 在stl中map和set的结构中&#xff0c;他们都使用一个红黑树进行封装。 由上图可知&a…

Java 枚举和注解

一、枚举类 把具体的对象一个一个例举出来的类就称为枚举类 枚举对应英文(enumeration, 简写 enum)枚举是一组常量的集合。可以这里理解&#xff1a;枚举属于一种特殊的类&#xff0c;里面只包含一组有限的特定的对象。 1.实现方式1——自定义类实现枚举 public class Enume…

Oracal学习

Oracle是什么 是甲骨文公司的一款支持事务且吞吐量高的数据库特点&#xff1a; &#xff08;1&#xff09;支持多用户、大事务量的事务处理 &#xff08;2&#xff09;数据安全性和完整性控制 &#xff08;3&#xff09;支持分布式数据处理 &#xff08;4&#xff09;可移植性…

【C++】C++入门基础讲解(一)

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 导读 经过一段时间的C语言学习&#xff0c;我们以及基本掌握了C语言的知识&#xff0c;今天&#xff0c;我们就开始学习C&#xff0c;…

2024最新幻兽帕鲁服务器多少钱一个?

幻兽帕鲁服务器多少钱&#xff1f;价格便宜&#xff0c;阿里云4核16G幻兽帕鲁专属服务器32元1个月、66元3个月&#xff0c;4核32G配置113元1个月、339元3个月&#xff1b;腾讯云4核16G14M服务器66元1个月、277元3个月、1584元一年。阿腾云atengyun.com分享阿里云和腾讯云palwor…

SpringBoot的自动装配原理

一、SpringBootConfiguration注解的作用 SpringBootApplication注解是SpringBoot项目的核心注解,加在启动引导类上。点击进去可以发现SpringBootApplication注解是一个组合注解。其中SpringBootConfiguration和EnableAutoConfiguration是由Spring提供的,剩下的注解是由JDK提供的…

简单计算与模拟1:鸡兔同笼(POJ 3237)

1 问题描述 图1 问题描述 2 解题思路 鸡有两只脚&#xff0c;兔子有四只脚&#xff0c;且输入数据可能为奇数&#xff0c;使用公式计算即可。 3 设计代码 #include <cstdio> int main() {int nCases, nFeets;while (scanf("%d", &nCases) ! EOF){for (in…

负载均衡-Ribbon-自定义负载均衡算法

1.Ribbon 是什么 SpringCloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端负载均衡的工具主要功能是提供客户端的软件负载均衡算法&#xff0c;将 Netflix 的中间服务处连接在一起Ribbon的客户端组件提供一系列完整的配置项&#xff0c;如&#xff1a;连接超时、重试等。简…

echarts 绘制垂直滚动热力图

问题1&#xff1a;提示功能无效 问题2&#xff1a;值筛选无效 效果 在线浏览 下载echarts官网例子(heatmap Examples - Apache ECharts) 稍作改动&#xff1a; generateData 入参改为长度和宽度noise.perlin2(i / 40, j / 20) Math.random() * 5y轴倒置指定zlevel为2 通过定…

蓝桥杯备战——7.DS18B20温度传感器

1.分析原理图 通过上图我们可以看到DS18B20通过单总线接到了单片机的P14上。 2.查阅DS18B20使用手册 比赛的时候是会提供DS18B20单总线通讯协议的代码&#xff0c;但是没有提供读取温度数据的代码&#xff0c;所以还是需要我们去查看手册&#xff0c;我只把重要部分截下来了 …

python-自动篇-运维-根据计算机硬盘、主板、CPU生成注册信息

文章目录 准备代码效果 准备 本实例需要使用WMI模块&#xff0c;所以需要安装WMI模块。在安装WMI模块之前&#xff0c;先要安装pywin32模块&#xff0c;WMI模块需要win32api的支持。使用pip安装pywin32模块和WMI模块的代码如下&#xff1a; pip install win32com pip install …

Ubuntu 22.04 安装tomcat

tomcat是常用的Java服务容器,这篇文章我们就来讲讲如何安装它。 更新软件包 首先是更新软件包,这是最常规的操作 sudo apt update 然后是开始安装,不多一会就可以安装好了 sudo apt install tomcat9 然后看一下状态 sudo systemctl status tomcat9 发现虽然启动了,但…

Python第十一章(推导式)

一。列表推导式&#xff1a;目的化简代码&#xff0c;可以改变数据 例句1&#xff1a;如果while循环继续创建序列累加 例句2&#xff1a;如果for循环进行列表累加 1.循环列表推导式进行累加&#xff1a; 注释&#xff1a;第一个i表示的是返回的数据于列表&#xff0c;for后面内…

windows上使用anconda安装tensorrt环境

windows上使用anconda安装tensorrt环境 1 安装tensorrt1.1 下载最新的稳定的tensorrt 8.6.1(tensorrt对应的cuda、cudnn等版本是参考链接4)1.2 将tensorrt添加到环境变量1.3 安装tensorrt依赖1.4 安装Pycuda1.5 安装pytorch 2 测试2.1 测试TensorRT 样例(这个测试主要来源于参考…

【Python】01快速上手爬虫案例一:搞定豆瓣读书

文章目录 前言一、VSCodePython环境搭建二、爬虫案例一1、爬取第一页数据2、爬取所有页数据3、格式化html数据4、导出excel文件 前言 实战是最好的老师&#xff0c;直接案例操作&#xff0c;快速上手。 案例一&#xff0c;爬取数据&#xff0c;最终效果图&#xff1a; 一、VS…

docker生命周期管理命令

文章目录 前言1、docker create2、docker run2.1、常用选项2.2、系统2.3、网络2.4、健康检查 3、docker start/stop/restart4、docker kill5、docker rm6、docker pause/unpause总结 前言 在云原生时代&#xff0c;Docker已成为必不可少的容器管理工具。通过掌握Docker常用的容…