当前位置: 首页 > news >正文

数据结构 模拟实现LinkedList单向不循环链表

目录

一、链表的简单介绍

二、链表的接口

三、链表的方法实现

(1)display方法

(2)size得到单链表的长度方法

(3)addFirst头插方法

(4)addLast尾插方法

(5)addIndex指定位置插入方法

(6)contains方法

(7)remove删除第一个key值节点的方法

(8)removeAllKey删除所有值为key的方法

(9)clear方法

四、最终代码


一、链表的简单介绍

概念:链表是一种物理存储结构不连续,逻辑上是连续的;链表类似现实中的火车,一节车厢连着一节车厢,而链表是通过链表之间的引用进行连接,构成一节一节的数据结构。如图:


二、链表的接口

代码如下:

public interface Ilist {//头插法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();
}

三、链表的方法实现

创建一个类,实现接口,重写方法,链表中的方法都在里面实现。类里面有链表类,也是内部类,有val值,next域,还有记录第一个节点的头结点,代码如下:

public class MyLinkedList implements Ilist{public ListNode head;static class ListNode{int val;ListNode next;public ListNode(int val) {this.val = val;}}
}

我们先创建一个方法,方法里面会创建几个节点,代码如下:

public void createList() {ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(23);ListNode node3 = new ListNode(34);ListNode node4 = new ListNode(45);ListNode node5 = new ListNode(56);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node5;this.head = node1;}

调用这个方法,就会创建出含有5个节点的链表,在test类里面创建main方法,调用此方法后的结果,结果如图:

(1)display方法

此方法可以显示链表中所有元素,也就是遍历一遍链表,打印val值,代码如下:

public void display() {ListNode cur = head;while (cur != null) {System.out.print(cur.val + " ");cur = cur.next;}System.out.println();}

调用该方法执行结果如下:

(2)size得到单链表的长度方法

要得到链表的长度,就要遍历一遍链表,定义一个变量进行统计个数,代码如下:

public int size() {int count = 0;ListNode cur = head;while (cur != null) {count++;cur = cur.next;}return count;}

执行结果:

(3)addFirst头插方法

头插就要把要插入的节点当做头结点,要插入的元素next域指向当前头结点,再把头结点定成插入的元素。

代码:

public void addFirst(int data) {ListNode node = new ListNode(data);if(this.head == null) {this.head = node;} else {node.next = this.head;this.head = node;}}

调用此方法,多条语句后的执行结果如下:

(4)addLast尾插方法

尾插就是要在链表的尾节点后插入节点,代码如下:

public void addLast(int data) {ListNode node = new ListNode(data);if(this.head == null) {this.head = node;} else {ListNode cur = this.head;while (cur.next != null) {cur = cur.next;}cur.next = node;}}

执行结果如下:

(5)addIndex指定位置插入方法

我们这里规定第一个节点的位置是0,第二个节点位置为1,依次往后推,我们要指定某一位置插入节点,先要检查插入位置是否合法,不合法抛出异常;合法在指定位置插入节点,如果指定位置是0,就是头插,指定位置是节点个数的size,就是尾插;中间位置,我们要找到指定位置的前一个节点,插入节点的next域指向前一个节点的next节点,前一个节点的next域指向插入节点,代码如下:

    public void addIndex(int index, int data) {try {if(index < 0 || index > size()) {throw new IndexException("下标异常,下标:" + index);} else {if(index == 0) {//头插addFirst(data);return;}if (index == size()) {//尾插addLast(data);return;}ListNode node = new ListNode(data);ListNode cur = searchPrev(index);node.next = cur.next;cur.next = node;}} catch (IndexException e) {e.printStackTrace();}}//找到链表前一个的位置private ListNode searchPrev(int index) {ListNode cur = this.head;int count = 0;while (count != index - 1) {cur = cur.next;count++;}return cur;}public class IndexException extends RuntimeException{public IndexException(String e) {super(e);}
}

(6)contains方法

查找是否包含关键字key是否在单链表当中,遍历一遍链表,有该元素就返回true,没有就返回false,代码如下:

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

(7)remove删除第一个key值节点的方法

删除一个节点,先要判断该链表为不为空,为空就退出;不为空,看要删的节点是不是头结点,是头结点就直接把头结点改成头结点的next域;要删除的节点可能在中间,就要扎到要删除节点的前一个节点,把前一个节点的next域指向要删除节点的next域就好了,代码如下:

public void remove(int key) {if(this.head == null) {//一个节点都没有,无法删除return;}if(this.head.val == key) {this.head = this.head.next;return;}ListNode cur = findPrev(key);if(cur == null) {System.out.println("没有要删除的点");} else {ListNode del = cur.next;cur.next = del.next;}}private ListNode findPrev(int key) {ListNode cur = this.head;while (cur.next != null) {if(cur.next.val == key) {break;}cur = cur.next;}return cur == this.head ? null : cur;}

执行结果如下:

(8)removeAllKey删除所有值为key的方法

如果头结点是空的,就不用进行下面操作,直接返回。

两个节点,一个的前节点,一个是前节点的后一个节点,遍历后一个节点,判断后一个节点的val值是不是key,是key就把前一个节点的next域指向后一个节点的next域,后一个节点向后移,没有命中后一个节点==key这条件,前一个节点和后一个节点都要往后移动一步。

最后还要判断头结点的val值是否等于key值,是就要把head标记成head的next域。

代码入如下:

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

执行结果如下:

(9)clear方法

清除所有节点,有两种解决方案,第一种是直接把头结点设为空,这种方法比较暴力;第二种是把每个节点的next域设为空,同时val也要设为空,因为这里的val类型是int,所以就设置不了空了,最后再把head节点设为空,代码如下:

 public void clear() {ListNode cur = this.head;while (cur != null) {ListNode curNext = cur.next;cur.next = null;cur = curNext;}head = null;}

执行结果如下:


四、最终代码

public class MyLinkedList implements Ilist{public ListNode head;static class ListNode{int val;ListNode next;public ListNode(int val) {this.val = val;}}public void createList() {ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(23);ListNode node3 = new ListNode(34);ListNode node4 = new ListNode(45);ListNode node5 = new ListNode(56);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node5;this.head = node1;}@Overridepublic void addFirst(int data) {ListNode node = new ListNode(data);if(this.head == null) {this.head = node;} else {node.next = this.head;this.head = node;}}@Overridepublic void addLast(int data) {ListNode node = new ListNode(data);if(this.head == null) {this.head = node;} else {ListNode cur = this.head;while (cur.next != null) {cur = cur.next;}cur.next = node;}}@Overridepublic void addIndex(int index, int data) {try {if(index < 0 || index > size()) {throw new IndexException("下标异常,下标:" + index);} else {if(index == 0) {//头插addFirst(data);return;}if (index == size()) {//尾插addLast(data);return;}ListNode node = new ListNode(data);ListNode cur = searchPrev(index);node.next = cur.next;cur.next = node;}} catch (IndexException e) {e.printStackTrace();}}//找到链表前一个的位置private ListNode searchPrev(int index) {ListNode cur = this.head;int count = 0;while (count != index - 1) {cur = cur.next;count++;}return cur;}@Overridepublic boolean contains(int key) {ListNode cur = this.head;while (cur != null) {if(cur.val == key) {return true;}cur = cur.next;}return false;}@Overridepublic void remove(int key) {if(this.head == null) {//一个节点都没有,无法删除return;}if(this.head.val == key) {this.head = this.head.next;return;}ListNode cur = findPrev(key);if(cur == null) {System.out.println("没有要删除的点");} else {ListNode del = cur.next;cur.next = del.next;}}private ListNode findPrev(int key) {ListNode cur = this.head;while (cur.next != null) {if(cur.next.val == key) {break;}cur = cur.next;}return cur == this.head ? null : cur;}@Overridepublic void removeAllKey(int key) {if(this.head == null) {return;}ListNode prev = this.head;ListNode cur = this.head.next;while (cur != null) {if(cur.val == key) {prev.next =cur.next;cur = cur.next;} else {cur = cur.next;prev = prev.next;}}if(this.head.val == key) {this.head = this.head.next;}}@Overridepublic int size() {int count = 0;ListNode cur = head;while (cur != null) {count++;cur = cur.next;}return count;}@Overridepublic void clear() {ListNode cur = this.head;while (cur != null) {ListNode curNext = cur.next;cur.next = null;cur = curNext;}head = null;}@Overridepublic void display() {ListNode cur = head;while (cur != null) {System.out.print(cur.val + " ");cur = cur.next;}System.out.println();}
}//自定义异常类
public class IndexException extends RuntimeException{public IndexException(String e) {super(e);}
}

点个赞再走吧,谢谢谢谢谢!

相关文章:

数据结构 模拟实现LinkedList单向不循环链表

目录 一、链表的简单介绍 二、链表的接口 三、链表的方法实现 &#xff08;1&#xff09;display方法 &#xff08;2&#xff09;size得到单链表的长度方法 &#xff08;3&#xff09;addFirst头插方法 &#xff08;4&#xff09;addLast尾插方法 &#xff08;5&#xf…...

2023-12-24 LeetCode每日一题(收集足够苹果的最小花园周长)

2023-12-24每日一题 一、题目编号 1954. 收集足够苹果的最小花园周长二、题目链接 点击跳转到题目位置 三、题目描述 给你一个用无限二维网格表示的花园&#xff0c;每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| |j| 个苹果。 你将会买下正中心坐…...

Oracle 19c OCP 1z0 082考场真题解析第17题

考试科目&#xff1a;1Z0-082 考试题量&#xff1a;90 通过分数&#xff1a;60% 考试时间&#xff1a;150min 本文为云贝教育郭一军guoyJoe原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 17. Which three …...

掌握这十几个Python库才是爬虫界的天花板,没有你搞不定的网站!实战案例:Python全网最强电影搜索工具,自动生成播放链接

掌握这十几个Python库才是爬虫界的天花板,没有你搞不定的网站!实战案例:Python全网最强电影搜索工具,自动生成播放链接。 用来爬虫的十几个Python库。只要正确选择适合自己的Python库才能真正提高爬虫效率,到达高效爬虫目的。 1.PyQuery from pyquery import PyQuery as …...

模型 KANO卡诺模型

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。需求分析。 1 卡诺模型的应用 1.1 餐厅需求分析故事 假设你经营一家餐厅&#xff0c;你想了解客户对你的服务质量的满意度。你可以使用卡诺模型来收集客户的反馈&#xff0c;并分析客户的…...

启明智显开源项目分享|基于Model 3c芯片的86中控面板ZX3D95CM20S-V11项目软硬件全开源

前言&#xff1a; 本文为4寸 480*480 RGB接口IPS全面触屏的86中控面板&#xff08;RT-ThreadLVGL&#xff09;软硬件开源干货内容&#xff0c;该项目是综合性非常强的RTOS系列项目&#xff01;项目主控芯片使用 Model 3c&#xff0c;整体实现了简化版本的86中控面板的功能需求…...

Kind创建k8s - JAVA操作控制

kind 简介kind 架构安装 Kind (必备工具)docker官网kubectl官网kind官网校验安装结果 关于kind 命令 安装一个集群查看当前 Kubernetes 集群中的节点信息。查看当前命名空间下中的Pod&#xff08;容器实例&#xff09;的信息。使用 kind create cluster 安装&#xff0c;关于安…...

Qt sender()函数

sender函数原型&#xff1a; QObject *sender() const; 如果在由信号激活的插槽中调用该函数&#xff0c;返回指向发送信号的对象的指针&#xff0c;否则返回0&#xff0c;该指针仅在从该对象的线程上下文调用此函数的槽执行期间有效。 主要代码如下&#xff1a; 其中运用了Q…...

Java开发框架和中间件面试题(6)

目录 61.什么是Spring Batch&#xff1f; 62.请举例解释Required与Qualifier注解&#xff1f; 61.什么是Spring Batch&#xff1f; Spring batch是一个轻量级的&#xff0c;完善的批处理框架&#xff0c;他主要的目的在于帮助企业建立健壮&#xff0c;高效的批处理应用。Spri…...

附录E SQL入门之SQL保留字

本专栏目录 第1课 SQL入门之了解SQL 第2课 SQL入门之检索数据 第3课 SQL入门之排序检索数据 第4课 SQL入门之过滤数据 第5课 SQL入门之高级数据过滤 第6课 SQL入门之用通配符进行过滤 第7课 SQL入门之创建计算字段 第8课 SQL入门之使用数据处理函数 第9课 SQL入门之汇总数据 第…...

thinkphp6.0升级到8.0

目录 一&#xff1a;升级过程 二&#xff1a;报错处理 最近写的项目需要使用thinkphp8.0&#xff0c;之前的老项目需要从php6.0升级到8.0&#xff0c;特此记录下升级过程。 一&#xff1a;升级过程 查看版本&#xff1a; php think version,我目前的版本是6.1.4 生成thin…...

机器学习(一) -- 概述

系列文章目录 机器学习&#xff08;一&#xff09; -- 概述 机器学习&#xff08;二&#xff09; -- 数据预处理 未完待续…… 目录 系列文章目录 前言 一、机器学习定义&#xff08;是什么&#xff09; 二、机器学习的应用&#xff08;能做什么&#xff09; 三、***机器…...

SpringBoot定时监听RocketMQ的NameServer

问题分析 自己在测试环境部署了RocketMQ&#xff0c;发现namesrv很容易挂掉&#xff0c;于是就想着监控&#xff0c;挂了就发邮件通知。查看了rocketmq-dashboard项目&#xff0c;发现只能监控Broker&#xff0c;遂放弃这一路径。于是就从报错的日志入手&#xff0c;发现最终可…...

电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

在数字化时代&#xff0c;采购管理也正经历着前所未有的变革。全过程数字化采购管理成为了企业追求高效、透明和规范的关键。该系统通过Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;打造了从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通过…...

各部门请注意,VELO维乐潮流骑士尼莫出街啦,快来加入吧!

VELO潮流骑士丨车界“小学生”尼莫&#xff0c;下面是来自她的自诉&#xff1a;      大家好&#xff01;我是尼莫&#xff0c;一枚骑车届的“小学生”&#xff0c;我爱上骑车已经有一年的时间啦&#xff01;在这一年的时间里&#xff0c;骑车改变了我很多&#xff1a;爱上…...

Flutter配置Android和IOS允许http访问

默认情况下&#xff0c;Android和IOS只支持对https的访问&#xff0c;如果需要访问不安全的连接&#xff0c;也就是http&#xff0c;需要做以下配置。 Android 在res目录下的xml目录中(如果不存在&#xff0c;先创建xml目录)&#xff0c;创建一个xml文件network_security_con…...

[设计模式 Go实现] 创建型~抽象工厂模式

抽象工厂模式用于生成产品族的工厂&#xff0c;所生成的对象是有关联的。 如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。 比如本例子中使用RDB和XML存储订单信息&#xff0c;抽象工厂分别能生成相关的主订单信息和订单详情信息。 如果业务逻辑中需要替换使用的时候…...

移动端开发框架mui代码在安卓模拟器上运行(HbuilderX连接到模拟器)

开发工具 HBuilder X 3.8.12.20230817 注意&#xff1a;开发工具尽量用最新的或较新的。太旧的版本在开发调试过程中可能会出现莫名其妙的问题。 1、电脑下载安装安卓模拟器 我这里使用的是 夜神模拟器 &#xff0c;也可以选择其他安卓模拟器 夜神模拟器官网&#xff1a;夜神安…...

upload-labs Pass-03(黑名单验证,特殊后缀)问题纠正

php任何后缀名解析 背景&#xff1a;为了验证php解析不依靠后缀名&#xff0c;可以是任何后缀名&#xff0c;纠正upload-labs Pass-03&#xff08;黑名单验证&#xff0c;特殊后缀&#xff09;里所说的几个固定的后缀名理论是错误的。1 部署1.1 环境准备1.1.1 系统、内核&#…...

微信小程序-父子页面传值

父子页面传值 父页面向子页面传值 方法一&#xff1a; 父页面&#xff1a; 1. /page/xxx/xxx?id1子页面&#xff1a; onLoad:function(option){ }方法二 <bindtap“func” data-xxx””> 子页面向父页面传值 定义父子页面 父页面&#xff1a;hotspot 子页面&a…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...