目录

链表的介绍

单链表的手动实现

单链表的基本框架

打印链表:

获取表长:

头插法新增节点:

尾插法新增节点:

在指定下标插入:

链表的查找

 删除链表中第一个出现的key:

删除链表中所有key值

链表置空

 总代码

测试代码

 链表相关的OJ题

1.反转单链表

 思路:​

2.查找链表中间节点

 思路:1.判空;2.定义两个指针,都指向head;3.设置循环,每次循环一个指针走两步一个指针走一步,当走的快的那个指针到达最后一个节点时,慢的节点就在中间;


链表的介绍

基于顺序表具有,插入数据,空间不足时要扩容,扩容有性能消耗和插入删除数据时有时候需要大量的挪动数据,导致程序的执行效率低的缺点,延升出了链表。

链表,是一种逻辑结构连续物理结构不一定连续的一种数据结构;由一个个的节点组成,每个节点包含数据域和指针域,指针域指向下一个节点。

单链表的手动实现

单链表的基本框架

//不带头结点的单链表
public class MySingleList implements IList{//链表由若干个头结点组成,每个节点都是一个完整的部分,所以可以定义一个内部类static class ListNode{public int val;//数据域public ListNode next;//指针域 存放下一个节点的地址public ListNode(int val) {this.val = val;}}public ListNode head;//定义一个存放节点的变量,默认值为null@Overridepublic void addFirst(int data) {}@Overridepublic void addLast(int data) {}@Overridepublic void addIndex(int index, int data) {}@Overridepublic boolean contains(int key) {return false;}@Overridepublic void remove(int key) {}@Overridepublic void removeAllKey(int key) {}@Overridepublic int size() {return 0;}@Overridepublic void clear() {}@Overridepublic void display() {}
}

为了更好的理解这个单链表的操作,我们先创建单链表的方法:

    public ListNode head;//定义一个存放节点的变量,默认值为nullpublic void createList(){//1.通过实例化ListNode创建几个节点ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(22);ListNode node3 = new ListNode(32);ListNode node4 = new ListNode(42);//2.根据单链表的形态,把节点链接起来node1.next = node2;node2.next = node3;node3.next = node4;this.head = node1;}

打印链表:

    public void display() {//1.借助一个cur节点去遍历链表,移动cur的位置ListNode cur = head;while (cur !=null){//cur=null表示整个链表都走完了System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}

注意区分循环条件 cur !=null 和cur.next !=null

获取表长:

获取表长的方法是打印方法衍生出来的,无非就是打印的方法中加一个计数器去记表长:

    public int size() {ListNode cur = head;int count = 0;while (cur != null){//注意这个循环条件count++;cur = cur.next;}return count;}

头插法新增节点:

    public void addFirst(int data) {//1.实例化一个节点ListNode node = new ListNode(data);//2.新增节点的指针域指向头节点更新头结点 顺序不可变node.next = head;this.head = node;}

 注意:

  • 插入数据时先绑定后面,如果我们先绑定前面的话会发生什么呢?当this.head = node先执行的完后,新增节点指针域该指向谁了,为了防止数据丢失,插入数据时因先绑定后面

尾插法新增节点:

    public void addLast(int data) {ListNode node = new ListNode(data);//1.找到链表最后一个节点if (head == null){head = node;}else {//遍历链表去找ListNode cur = head;while (cur.next != null) {cur = cur.next;}cur.next = node ;//增}}

在指定下标插入:

    public void addIndex(int index, int data) {//1.判断index的合法性if (index < 0 || index > size()){throw new IndexException("index非法"+index);}//表空的情况ListNode node = new ListNode(data);if (head == null){head = node;return;}//2.在0位置插入时调用头插if (index == 0 ){addFirst(data);return;}//3.index=size()尾插法if (index == size()){addLast(data);return;}//在index位置插入时,找到index位置的前一个节点去操作ListNode cur = findPrevIndex(index);node.next = cur.next;cur.next = node;}private ListNode findPrevIndex(int index){ListNode cur = head;int count = 0;while (count != index - 1){count++;cur = cur.next;}return cur;}

链表的查找

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

 删除链表中第一个出现的key:

   public void remove(int key) {//1.表空if (head == null){return;}//2.头结点删除if (head.val == key){head = head.next;return;}//3.中间元素删除找key的前驱节点去操作ListNode cur = findPrevKey(key);cur.next = cur.next.next;//也可以借助一个变量去删除/*ListNode del = cur.next;cur.next = del.next;*/}//尽量以方法的方式去实现功能,降低代码的耦合度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;}

删除链表中所有key值

    public 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;}}}

链表置空

    public void clear() {//法1:循环把每个节点都置空//法2:直接把最开始的节点中(只要是没有人引用的对象内存都会回收置空),这样就把整个链表置空了head = null;}

 总代码

//不带头结点的单链表
public class MySingleList implements IList{//链表由若干个头结点组成,每个节点都是一个完整的部分,所以可以定义一个内部类static class ListNode{public int val;//数据域public ListNode next;//指针域 存放下一个节点的地址public ListNode(int val) {this.val = val;}}public ListNode head;//定义一个存放节点的变量,默认值为nullpublic void createList(){//1.通过实例化ListNode创建几个节点ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(22);ListNode node3 = new ListNode(32);ListNode node4 = new ListNode(42);//2.根据单链表的形态,把节点链接起来node1.next = node2;node2.next = node3;node3.next = node4;this.head = node1;}@Overridepublic void addFirst(int data) {//1.实例化一个节点ListNode node = new ListNode(data);//2.新增节点的指针域指向头节点更新头结点node.next = head;this.head = node;}@Overridepublic void addLast(int data) {ListNode node = new ListNode(data);//1.找到链表最后一个节点if (head == null){head = node;}else {//遍历链表去找ListNode cur = head;while (cur.next != null) {cur = cur.next;}cur.next = node ;//增}}@Overridepublic void addIndex(int index, int data) {//1.判断index的合法性if (index < 0 || index > size()){throw new IndexException("index非法"+index);}//表空的情况ListNode node = new ListNode(data);if (head == null){head = node;return;}//2.在0位置插入时调用头插if (index == 0 ){addFirst(data);return;}//3.index=size()尾插法if (index == size()){addLast(data);return;}//在index位置插入时,找到index位置的前一个节点去操作ListNode cur = findPrevIndex(index);node.next = cur.next;cur.next = node;}private ListNode findPrevIndex(int index){ListNode cur = head;int count = 0;while (count != index - 1){count++;cur = cur.next;}return cur;}@Overridepublic boolean contains(int key) {ListNode cur = head;while (cur !=null){if (cur.val == key){return true;}cur = cur.next;}return false;}@Overridepublic void remove(int key) {//1.表空if (head == null){return;}//2.头结点删除if (head.val == key){head = head.next;return;}//3.中间元素删除找key的前驱节点去操作ListNode cur = findPrevKey(key);cur.next = cur.next.next;//也可以借助一个变量去删除/*ListNode del = cur.next;cur.next = del.next;*/}//尽量以方法的方式去实现功能,降低代码的耦合度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;}@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;}}}@Overridepublic int size() {ListNode cur = head;int count = 0;while (cur != null){count++;cur = cur.next;}return count;}@Overridepublic void clear() {//法1:循环把每个节点都置空//法2:直接把最开始的节点中(只要是没有人引用的对象内存都会回收置空),这样就把整个链表置空了head = null;}@Overridepublic void display() {if (head == null){System.out.println("链表为空");return;}//1.借助一个cur节点去遍历链表,移动cur的位置ListNode cur = head;while (cur !=null){//cur=null表示整个链表都走完了System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}}

测试代码

public class Test {public static void main(String[] args) {MySingleList mySingleList = new MySingleList();mySingleList.createList();System.out.println();mySingleList.display();//12 22 32 42System.out.println(mySingleList.size());//4mySingleList.addFirst(2);mySingleList.display();//2 12 22 32 42mySingleList.addLast(52);mySingleList.display();//2 12 22 32 42 52mySingleList.addIndex(2,20);mySingleList.display();//2 12 20 22 32 42 52System.out.println(mySingleList.contains(52));//truemySingleList.remove(12);mySingleList.display();//2 20 22 32 42 52mySingleList.addLast(2);mySingleList.addIndex(3,2);mySingleList.display();//2 20 22 2 32 42 52 2mySingleList.removeAllKey(2);mySingleList.display();//20 22 32 42 52mySingleList.clear();mySingleList.display();//链表为空}
}

 链表相关的OJ题

1.反转单链表

反转一个单链表

 思路:

    public ListNode reverseList(){if (head == null){return null;}if (head.next == null){return head;}//ListNode cur = head.next;//定义一个cur记录当前需要反转的节点head.next = null;while(cur != null){ListNode curNext = cur.next;//记录下一个反转点cur.next = head;//当前要反转的节点指向headhead = cur;//更新headcur = curNext;//更新cur}return head;}

2.查找链表中间节点

题目

 思路:1.判空;2.定义两个指针,都指向head;3.设置循环,每次循环一个指针走两步一个指针走一步,当走的快的那个指针到达最后一个节点时,慢的节点就在中间;

    public ListNode middleNode(){if (head == null){return null;}ListNode fast = head;ListNode slow = head;while (fast != null && fast.next !=null){//顺序不能反,否则报空指针异常fast = fast.next.next;slow = slow.next;}return slow;}

 感谢大家阅读📚点赞👍收藏⭐评论✍关注❤

博客主页: 【长毛女士-CSDN博客 

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

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

相关文章

梯度提升之原理

简介 梯度提升主要是基于数学最值问题 数学描述 目标函数为 obj(θ)∑i1nl(yi,y^i(t))∑k1tw(fk)obj(\theta) \sum_{i1}^n l(y_i, \hat y_i^{(t)}) \sum_{k1}^t w(f_k)obj(θ)i1∑n​l(yi​,y^​i(t)​)k1∑t​w(fk​) 其中ttt表示集成的树的个数&#xff0c;y^i(t)y^i(t−1)…

[学习] Hilbert变换:从数学原理到物理意义的深度解析与仿真实验(完整实验代码)

Hilbert变换&#xff1a;从数学原理到物理意义的深度解析与仿真实验 文章目录Hilbert变换&#xff1a;从数学原理到物理意义的深度解析与仿真实验一、数学原理二、作用与物理意义1.构造解析信号2.相位移动特性3.应用场景三、仿真实验实验1&#xff1a;正弦信号的Hilbert变换实验…

对话弋途科技:当AI重构汽车大脑,一场车载操作系统的“觉醒年代“开始了

&#xff08;图片来源&#xff1a;Pixels&#xff09;站在未来看历史&#xff0c;AI汽车刚刚开始。数科星球原创作者丨苑晶编辑丨大兔当特斯拉的自动驾驶仍在全球引发争议时&#xff0c;中国智能汽车战场已悄然开启第二幕。从"四个轮子的大手机"到"移动智能空间…

❗机器学习量化交易模型全面剖析报告基于因子库的机器学习交易模型构建指南

目录 第一章&#xff1a;机器学习在加密货币量化交易中的应用概述 范式转变&#xff1a;从传统因子到机器学习驱动的策略 为什么选择机器学习&#xff1f;机遇、挑战与核心概念 机遇 挑战 核心概念 第二章&#xff1a;为机器学习准备您的因子库 理解量化因子作为机器学…

内容创作智能体:多模态内容生成的完整解决方案

内容创作智能体&#xff1a;多模态内容生成的完整解决方案 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…

测试学习之——Pytest Day4

Pytest作为Python中功能强大且易于使用的测试框架&#xff0c;深受开发者喜爱。它不仅提供了简洁的测试编写方式&#xff0c;还通过丰富的配置选项、灵活的标记机制和强大的数据驱动能力&#xff0c;极大地提升了测试效率和可维护性。本文将深入探讨Pytest的配置意义与层级、常…

【软件系统架构】系列七:系统性能——路由器性能深入解析

目录 一、路由器的核心功能 二、路由器性能核心指标 1. 吞吐量&#xff08;Throughput&#xff09; 2. 并发连接数&#xff08;Session Capacity&#xff09; 3. 每秒连接数&#xff08;CPS&#xff0c;Connections Per Second&#xff09; 4. 转发延迟&#xff08;Laten…

【数据结构】第一讲 —— 概论

【数据结构】第一讲 —— 概论 文章目录【数据结构】第一讲 —— 概论1.1 基本概念和常用术语1.2 了解数据结构1. 数据结构2. 数据的逻辑结构3. 数据的物理结构&#xff08;存储结构&#xff09;4. 数据的运算1.3 算法的描述和分析1.3.1 算法的描述1.3.21.1 基本概念和常用术语…

全面解析MySQL(2)——CRUD基础

1.CreateCreate(创建)&#xff1a;添加新数据到数据库中#基础语法 insert into table_name (column1,column2,column3, ...) values (value1,value2,value3, ...);1.1 单行全列插入value中值的数量和顺序必须和column⼀致describe demo1; -----------------------------------…

某外企笔试总结——纯C语言

这里写自定义目录标题一、sizeof 计算&#xff08;32位环境&#xff09;二、简答题三、数据存储区域与可修改性四、字符串比较输出及原因五、数组指针运算输出六、字符串倒序代码错误排查七、下面程序可以把1维数组转为2维数组&#xff0c;然后调用 printArr2D 打印出数组内容&…

Qt Graphs 模块拟取代 charts 和 data visualization还有很长的路要走

近期关注 Qt 6.10 的分支进展&#xff0c; 发现了 Qt 6.10 的 charts 和 data visualization &#xff08;以下简称 DV&#xff09;已经被deprecated, 功能将会合并到 graphs 模块。如果后面 charts\ DV 被弃用&#xff0c;那算是很大的API变化了。从Qt 6.5 以后开始引入的 gra…

2025牛客暑期多校训练营2(部分补题)

题目链接&#xff1a;牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ B Bitwise Perfect 思路 考虑到由&#xff0c;那么只有变小的时候对答案的贡献才能够减少&#xff0c;从二进制的角度考虑什么时候变小&#xff0c;只有min(x,y)中的最高位1异或之后变…

Nginx的location匹配规则

Nginx的location匹配规则 为什么你的Nginx配置总是不生效&#xff1f; 改了Nginx配置无数次&#xff0c;reload命令执行了几十遍&#xff0c;浏览器访问时却依然返回404&#xff1f;运维工程师小张上周就遇到了这个问题&#xff1a;明明配置了location /static/ { root /var/ww…

USB 2.0 vs USB 3.0:全面技术对比与选择指南

USB 2.0 vs USB 3.0&#xff1a;全面技术对比与选择指南 引言 在当今数字时代&#xff0c;USB接口已成为连接设备与计算机的最普遍标准之一。从2000年USB 2.0的发布到2008年USB 3.0的问世&#xff0c;USB技术经历了显著的演进。本文将深入比较这两种广泛使用的USB标准&#xff…

DApp架构设计与开发流程指南

目录 DApp架构设计与开发流程指南 引言:DApp的核心特性 一、DApp架构设计 1.1 分层架构设计 各层核心组件: 1.2 典型架构模式 1.2.1 全去中心化架构 1.2.2 混合架构(推荐) 二、开发流程 2.1 敏捷开发流程 2.2 详细开发阶段 阶段1:需求分析与设计(1-2周) 阶段2:智能合约…

Windows下odbc配置连接SQL Server

一、查看SQL Server服务是否启动打开SQL Server 2022配置管理器查看SQL Server运行状态&#xff0c;可以设置 启动或停止服务二、windows下如何配置ODBC数据源1、Windows搜索栏中输入“ODBC数据源管理器”并选择“以管理员身份运行”来打开它2、添加新的数据源ODBC数据源管理器…

MySQL—表设计和聚合函数以及正则表达式

文章目录一、第一范式&#xff08;原子性&#xff09;二、第二范式&#xff08;消除部分依赖&#xff09;三、第三范式&#xff08;消除传递依赖&#xff09;四、表设计五、聚合函数六、正则表达式MySQL 的三大范式&#xff08;1NF、2NF、3NF&#xff09;是关系型数据库设计的核…

基于Electron打包jar成Windows应用程序

基于Electron打包jar成Windows应用程序简介注意编译及命令&#xff1a;运行效果登录界面用户管理界面界面全屏锁屏界面文档查看界面简介 本文介绍了一种将maven jar包打包成Windows下EXE可执行程序的方法。 Maven打包Java Web应用成jar&#xff0c;Electron封装jar成Windows …

Autosar RTE实现观测量生成-基于ETAS软件

文章目录前言观测量定义arTypedPerInstanceMemoryPorts Measurable工具链配置及使用Port中的配置arTypedPerInstanceMemory观测量生成文件分析总结前言 之前我们在XCP中&#xff0c;对于标定量和观测量并没有严格按照Autosar标准中定义&#xff0c;Autosar RTE中对标定量和观测…

【REACT18.x】creat-react-app在添加eslint时报错Environment key “jest/globals“ is unknown

今天在创建新项目的时候&#xff0c;给cra创建的项目添加eslint支持&#xff0c;出现如下报错 添加eslint npx eslint --init页面报错 Compiled with problems:ERROR [eslint] package.json eslint-config-react-app/jest#overrides[0]:Environment key "jest/globals&…