数据结构:链表(1)
顺序表的优缺点
缺点:
1.插入数据必须移动其他数据,最坏情况下,就是插入到0位置。时间复杂度O(N)
2.删除数据必须移动其他数据,最坏情况下,就是删除0位置。时间复杂度O(N)
3.扩容之后,有可能会浪费空间。
优点:
在给定下标进行查找的时候
总结:顺序表比较适合进行给定下路查找的场景
🆗链表可以完美解决顺序表的缺点
链表是什么?
一个链表其实就是一辆火车

火车的每个车厢相当于一个节点,链表节点长这样

其中,数据域存储数据
而火车之间要有挂钩链接,这就需要next域出马了,next读取下一个节点的地址并把它记录在next域里面,下面这个图也是单向链表,一条路走到黑

分类
有六种分类

常见的是红色圈起来的两个
带头的长啥样?头部存的数据是无效的,跟这个链表没有关系,这个头节点的值永远不会改变

循环的?

双向的?两边都能走

链表结构特点:物理上不一定是连续的,但逻辑上是连续的
单向链表
手搓一个
初始化
实现方法有下面这些
//IList.java 接口
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();
}
再新建一个模块重写这些方法
public class MySingleList implements IList{@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() {}
}
ok!接下来我们要设置一个节点的内部类把要用到的属性加上
static class ListNode{public int val;public ListNode next; //定义next域//节点类构造方法public ListNode(int val){this.val = val;}}
为什么是static呢?因为每个节点都一样,都由数据域和next域组成的,直接static定义共同特点。
那第三行的ListNode next 怎么理解呢?因为next指向的是下一个节点的地址,而下一个节点的类型也是ListNode,所以这里的next一定是ListNode类型

好接下来定义一个链表的头
public ListNode head;
注意不要放到内部类里面,因为head是链表的成员而不是节点的成员
给几个节点赋上值

1.如何让node1的下一个节点是node2

node1.next = node2 //表示node2地址0x46给到node1
node1.next = node2; node2.next = node3; node3.next = node4; node4.next = node5;

node1是局部变量,整个过程走完之后node1会被回收怎么办?
两种方法:
第一种,把刚刚那个函数类型改成ListNode,函数返回node1
第二种,我们不是定义了head了吗,直接在函数末尾写上
this.head = node1; 这样就行了
检验结果

遍历列表
1.怎么从一个节点走到下一个节点

2.怎么判断所有节点都遍历完了

一个循环,循环终止条件是head为空,我们按照这个思想把display代码完成

这个代码有一个问题,遍历完列表之后head为空,整个头节点地址和值全都无了
解决办法是创一个中间变量cur把head锁死,遍历完之后cur为空了,但是head本质上不会变
@Overridepublic void display() {ListNode cur = this.head;while(cur != null){System.out.println(cur.val + " ");cur = cur.next;}}
有这个代码的基础,链表长度和包含函数也不在话下
@Overridepublic int size() {int count = 0;ListNode cur = this.head;while(cur != null){cur = cur.next;count++;}return count;}@Overridepublic boolean contains(int key) {ListNode cur = this.head;while(cur != null){if(cur.val == key){return true;}cur = cur.next;}return false;}
头插法
链表里面有节点


三步走
1. 实例化一个节点
2.改变插入节点的next
3.改变head
无节点
直接把head定义成这个节点
@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;}}
注意这个插入是倒叙插入
尾插法
指的是将待插入的节点存放到链表的最后一个位置
步骤:
1.实例化一个节点
2.把cur走到最后一个节点
3.cur.next = node; //插入下一个节点


@Overridepublic void addLast(int data) {ListNode node = new ListNode(data);ListNode cur = this.head;if (this.head == null){this.head = node;}else {//找到尾巴while (cur.next != null) {cur = cur.next;}//cur现在指向最后一个节点cur.next = node;}}
如果想要让cur停在最后一个节点的位置 cur.next != null;

如果想把整个链表都遍历完,就是cur != null;

注意:尾插法时间复杂度是O(N),因为要遍历完整个链表n个节点后才插入元素
在任意位置插入节点

1.让cur走index-1步
2.node.next = cur.next;
cur.next = node;
在插入一个节点的时候,一定要先绑定后面这个节点
@Overridepublic void addIndex(int index, int data) {if(index < 0 || index > size()){return;}if(index == size()){addLast(data);return;}ListNode cur = searchPrev(index);ListNode node = new ListNode(data);node.next = cur.next;cur.next = node;}private ListNode searchPrev(int index){ListNode cur = this.head;int count = 0;while(count!=index-1){cur = cur.next;count++;}return cur;}
删除元素

现在我们想删除第三个节点,把第三个节点设成del
在一个循环里面让cur遍历整个链表
判断 cur.next.val == key,找到cur的位置
后面cur = cur.next
@Overridepublic void remove(int key) {if(this.head == null){//一个节点都没有,删除不了return;}//删除头节点if(this.head.val == key){this.head = this.head.next;return;}//1、找到前驱ListNode cur = findPrev(key);//2、判断返回值是否为空?if(cur == null){System.out.println("没有你要删除的数字");return;}//3、删除ListNode del = cur.next;cur.next = del.next;}//找到关键字key的前一个节点的地址private ListNode findPrev(int key){ListNode cur = this.head;while(cur.next!=null){if(cur.next.val == key){return cur;}}return null;}
删除所有值为key的节点
比如下面删除所有值为23的节点

定义cur为当前要删除的节点
prev为当前要删除的节点的前驱

cur找到了就直接把prev的next地址改成cur下一个节点的地址,cur继续往下遍历
while(cur!=null){
if(cur.val == key){
prev.next = cur.next; //删除操作
cur = cur.next;
}else{
prev = cur;
cur = cur.next
}
}
@Overridepublic void removeAllKey(int key) {if(this.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;}}
清空链表
把一个节点的val = null, next = null
再把链表的head = null

注意:这里的val = null不是直接让你 cur.val = null,拿第一个节点来说,如果你把值置为空,那么0x46被替换成null,cur找不到下一个节点的地址0x46了
我们可以拿一个变量curNext来记录cur下一个节点的位置,把cur.next 置为空之后,cur往后挪到curNext的位置,继续置空下一个节点
注意别忘了头节点,整个遍历完之后还要把头节点也置为空
@Overridepublic void clear() {ListNode cur = this.head;while(cur!=null){ListNode curNext = cur.next;cur.next = null;cur = curNext;}head = null;}
相关文章:
数据结构:链表(1)
顺序表的优缺点 缺点: 1.插入数据必须移动其他数据,最坏情况下,就是插入到0位置。时间复杂度O(N) 2.删除数据必须移动其他数据,最坏情况下,就是删除0位置。时间复杂度O(N) 3.扩容之后,有可能会浪费空间…...
软件测试之概念篇2(瀑布模型、螺旋模型、增量模型和迭代模型、敏捷模型,V模型、W模型)
目录 开发模型 (1)瀑布模型 (2)螺旋模型 (3)增量模型和迭代模型 (4)敏捷模型 (5)测试模型(V模型、W模型) V模型 W模型 开发模型…...
【【萌新的SOC学习之重新起航SOC】】
萌新的SOC学习之重新起航SOC ZYNQ PL 部分等价于 Xilinx 7 系列 FPGA PS端:Zynq 实际上是一个以处理器为核心的系统,PL 部分可以看作是它的一个外设。 我们可以通过使用AXI(Advanced eXtensible Interface)接口的方式调用 IP 核,系统通过 AX…...
ElasticSearch 学习7 集成ik分词器
网上找了一大堆,很多都介绍的不详细,开始安装完一直报错找不到plugin-descriptor.properties,有些懵这个东西不应该带在里面吗,参考了一篇博客说新建一个这个,新建完可以启动,但是插入索引数据会报错找不到…...
[NewStarCTF 2023 公开赛道] week1
最近没什么正式比赛,都是入门赛,有moectf,newstar,SHCTF,0xGame都是漫长的比赛。一周一堆制。 这周newstar第1周结束了,据说py得很厉害,第2周延期了,什么时候开始还不一定,不过第一周已经结束提交了&#…...
ThreeJS-3D教学六-物体位移旋转
之前文章其实也有涉及到这方面的内容,比如在ThreeJS-3D教学三:平移缩放物体沿轨迹运动这篇中,通过获取轨迹点物体动起来,其它几篇文章也有旋转的效果,本篇我们来详细看下,另外加了tween.js知识点࿰…...
BC v1.2充电规范
1 JEITA Reference to https://www.mianbaoban.cn/blog/post/169964 符合 JEITA 规范的锂离子电池充电器解决方案 2 Battery Fuel Gauge 2.1 Cycle Count(充放电循环次数) 此指令回传一只读字段,代表电芯组已经历的完整充放电循环数。当放电容…...
判断一个整数是否回文
回文数字的定义:第一位和最后一位相等,第二位和倒数第二位相等...依次类推,比如1221,12321等等,也就是说一个数字如果是回文,那么将它反转之后,一定和原来的值相等 解法一:投机取巧,…...
【广州华锐互动】车辆零部件检修AR远程指导系统有效提高维修效率和准确性
在快速发展的科技时代,我们的生活和工作方式正在被重新定义。这种变化在许多领域都有所体现,尤其是在汽车维修行业。近年来,AR(增强现实)技术的进步为这个行业带来了前所未有的可能性。通过将AR技术与远程协助系统相结…...
简单实现接口自动化测试(基于python+unittest)
简介 本文通过从Postman获取基本的接口测试Code简单的接口测试入手,一步步调整优化接口调用,以及增加基本的结果判断,讲解Python自带的Unittest框架调用,期望各位可以通过本文对接口自动化测试有一个大致的了解。 引言 为什么要…...
【算法|双指针系列No.4】leetcode11. 盛最多水的容器
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望…...
数据结构全集介绍
以下列举了部分常见的数据结构: 数组(Array):数组是一种线性数据结构,可以用来存储固定大小的数据集合。在数组中,每个元素都有一个对应的索引,可以通过索引直接访问和更新元素。数组的优点是访…...
力扣刷题-字符串-反转字符串
344 反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 你可以假设数组中的所有字符都是 ASCII 码表中…...
【CCNP】第七章 动态路由协议-BGP
第一节 BGP的基本概念 BGP(Border Gateway Protocol),边界网关协议 是运行在网络和网络之间的协议,是一款EGP(外部网关协议) BGP基于TCP协议工作,目的端口号179。源端口随机,由路由…...
java学习--day24(stream流)
文章目录 今天的内容1.Stream【难点】1.1获取流的对象1.2Stream流对象下面1.2.1count和forEach1.2.2filter方法1.2.3limit1.2.4map方法1.2.5skip1.2.6concat 1.3收集流 1.基于接口和抽象类的匿名内部类的写法 abstract class Person {public abstract void eat(); } public sta…...
Multi-Grade Deep Learning for Partial Differential Equations
论文阅读:Multi-Grade Deep Learning for Partial Differential Equations with Applications to the Burgers Equation Multi-Grade Deep Learning for Partial Differential Equations with Applications to the Burgers Equation符号定义偏微分方程定义FNN定义PI…...
Docker部署rustdesk
查看镜像版本 https://hub.docker.com/r/rustdesk/rustdesk-server/tags 拉取镜像 docker pull rustdesk/rustdesk-server:1.1.8-2创建挂载目录 mkdir -p /opt/rustdesk/{hbbr,hbbs}/root运行hbbs –nethost 仅适用于 Linux,它让 hbbs/hbbr 可以看到对方真实的…...
win1011安装MG-SOFT+MIB+Browser+v10b
文章目录 安装MG-SOFTSNMP服务配置安装MG-SOFT启动MIB-Browser以及错误解决MIB Browser使用 安装MG-SOFT win10和win11安装基本一样,所以参照下面的操作即可! SNMP服务配置 打开设置,应用和功能,可选功能,选择添加功…...
PCL点云处理之Pcd文件读取、法线与曲率计算、多线程加速、属性字段合并 (二百零八)
PCL点云处理之Pcd文件读取、法线与曲率计算、多线程加速、属性字段合并(二百零八) 一、相关介绍二、算法实现1.代码一、相关介绍 (夜深人不静) 法线和曲率的计算是点云处理中常用的关键特征,PCL提供了特有的点类型PointNormal来记录这些信息,通过OMP多线程对相关的计算函…...
JavaEE-文件IO操作
构造方法 一般方法,有很多,我们以下只是列举几个经常使用的 注意在上述的操作过程中,无论是绝对路径下的这个文件还是相对路径下的这个文件,都是不存在的 Reader 使用 --> 文本文件 FileReader类所涉及到的一些方法 Fil…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
