java复习篇 数据结构:链表第二节 哨兵

目录

单向链表哨兵

初始

头插

思路

代码

尾插

思路

遍历

遍历验证头插

尾插代码

尾插测试

get

思路

代码

测试

insert

思路

代码

测试

remove

移除头结点

提问

移除指定位置

测试


单向链表哨兵

单向链表里面有一个特殊的节点称为哨兵节点,不存储数据。

优势:简化了单向链表的空判断,例如 尾插、get、insert、remove

初始

public class SentinelLinkedListTest {// 头指针 指向哨兵(666是任意定义的一个值)private Node head = new Node(666, null);// 节点类      private对外隐藏细节@Data@AllArgsConstructorprivate static class Node {private int value;private Node next;}}

将内部类定义为静态主要有两个原因:

实例化方式:静态内部类的实例化不需要依赖于外部类。而普通的内部类在实例化时会隐含地包含一个对外部类的引用,因此,普通的非静态内部类不能脱离外部类实例而单独存在。
访问方式:静态内部类可以使用静态方法直接通过类名来访问外部类的静态成员,而不需要创建外部类的实例。而普通的内部类需要先创建外部类的实例,然后通过该实例来访问外部类的静态成员。

头插

思路

对于使用者来说,我给你一个value值,你要将我的这个value值放入到链表头结点处。

不同于单向链表,这里一开始就有了哨兵

代码

    public void addFirst(int value) {head.next = new Node(value, head.next);}

哨兵的next指针指向新节点,新节点的next指针为之前哨兵的next指针指向的节点

尾插

思路

对于使用者来说,我给你一个value值,你要将我的这个value值放入到链表最后面

那我怎么知道你链表什么时候是最后面

遍历

遍历到最后一个节点,此时它的next指针指向null

注意:头指针是为了记录第一个节点地址,不能动,所以我定义一个可以移动的指针开始指向第一个节点

    public void foreach(Consumer<Integer> consumer) {Node p = head.next;while (p != null) {consumer.accept(p.value);p = p.next;}}

注:不同于单向链表,自定义的指针开始是指向哨兵的下一个节点地址。

遍历验证头插

public class SentinelTest {public static void main(String[] args) {SentinelLinkedListTest sentinelLinkedListTest = new SentinelLinkedListTest();sentinelLinkedListTest.addFirst(8);sentinelLinkedListTest.addFirst(7);sentinelLinkedListTest.addFirst(6);sentinelLinkedListTest.addFirst(5);sentinelLinkedListTest.foreach(System.out::println);}
}

为什么是倒序?

头插,先插的会随着后续插入一次次向后挪动

尾插代码

通过遍历,可以知道指针指向过最后一个节点后,然后指向了null

那让指针一直指,最后一次的下一个节点不为null时,为我们所需要的节点

    public void addLast(int value) {Node p = head;while (p.next != null) {p = p.next;}p.next = new Node(value, null);}

注意:不带哨兵的单向链表,如果链表啥也没有,那么p.next直接空指针

而现在头指针指向哨兵,就不可能存在空指针这种情况

尾插测试

public class SentinelTest {public static void main(String[] args) {SentinelLinkedListTest sentinelLinkedListTest = new SentinelLinkedListTest();sentinelLinkedListTest.addLast(99);sentinelLinkedListTest.foreach(System.out::println);}
}

get

思路

list(index)  是通过给一个索引,然后得到该索引对应位置的值。

对于链表,给一个索引,返回该节点的值。

代码

    public int get(int index) {Node node = findNode(index);if (node == null) throw new IllegalArgumentException("索引越界");return node.value;}public Node findNode(int index) {int i = -1;Node p = head;while (p != null) {if (i == index) {return p;} else {p = p.next;i++;}}return null;}

注:不同于单向链表,这里开始就让 i 为 -1 代表哨兵的位置      p 指向head,也就是哨兵

测试

public class SentinelTest {public static void main(String[] args) {SentinelLinkedListTest sentinelLinkedListTest = new SentinelLinkedListTest();sentinelLinkedListTest.addFirst(8);sentinelLinkedListTest.addFirst(7);sentinelLinkedListTest.addFirst(6);sentinelLinkedListTest.addFirst(5);sentinelLinkedListTest.addLast(99);sentinelLinkedListTest.foreach(System.out::println);System.out.println("====");System.out.println(sentinelLinkedListTest.get(4));}
}

insert

思路

我要向某个位置插入某个值,那么我需要知道这个位置的前面一个节点(其next 指向当前位置)

代码

    public void insert(int index, int value) {Node 前节点 = findNode(index - 1);if (前节点 == null) throw new IllegalArgumentException("索引越界");前节点.next = new Node(value, 前节点.next);}

此处现在也不同判断index为0时的插入,-1位置代表的就是哨兵

测试

public class SentinelTest {public static void main(String[] args) {SentinelLinkedListTest sentinelLinkedListTest = new SentinelLinkedListTest();sentinelLinkedListTest.addFirst(8);sentinelLinkedListTest.addFirst(7);sentinelLinkedListTest.addFirst(6);sentinelLinkedListTest.addFirst(5);sentinelLinkedListTest.addLast(99);sentinelLinkedListTest.foreach(System.out::println);System.out.println("====");System.out.println(sentinelLinkedListTest.get(4));System.out.println("====");sentinelLinkedListTest.insert(0, 100);sentinelLinkedListTest.foreach(System.out::println);}
}

remove

移除头结点

    public void removeFirst() {if (head.next == null) {return;}head.next = head.next.next;}

提问

移除的节点还存在,有没有因此而造成内存泄露?

不会,移除的节点无引用指向他,JVM垃圾回收会处理

移除指定位置

    public void remove(int index) {Node 前节点 = findNode(index - 1);if (前节点 == null) throw new IllegalArgumentException("索引越界");前节点.next = 前节点.next.next;}

测试

public class SentinelTest {public static void main(String[] args) {SentinelLinkedListTest sentinelLinkedListTest = new SentinelLinkedListTest();sentinelLinkedListTest.addFirst(8);sentinelLinkedListTest.addLast(99);sentinelLinkedListTest.foreach(System.out::println);System.out.println("====");sentinelLinkedListTest.insert(0, 100);sentinelLinkedListTest.foreach(System.out::println);System.out.println("====");sentinelLinkedListTest.removeFirst();sentinelLinkedListTest.foreach(System.out::println);System.out.println("====");sentinelLinkedListTest.remove(0);sentinelLinkedListTest.foreach(System.out::println);}
}

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

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

相关文章

C# AsyncLocal 是如何实现 Thread 间传值

一&#xff1a;背景 1. 讲故事 这个问题的由来是在.NET高级调试训练营第十期分享ThreadStatic底层玩法的时候&#xff0c;有朋友提出了AsyncLocal是如何实现的&#xff0c;虽然做了口头上的表述&#xff0c;但总还是会不具体&#xff0c;所以觉得有必要用文字图表的方式来系统…

强化数据资产管理,迎接数据资产 “入表” 新时代

2024年伊始&#xff0c;数据要素产业利好政策密集出台&#xff0c;数据资产“入表”成为了大势所趋。数据要素顶层设计方案加速落地&#xff0c;推动企业数字化转型提档加速&#xff0c;提升数据管理能力、实现数据资产价值成为企业下一阶段核心竞争力构建的关键。 01 数据资产…

pytorch与tensorflow如何选择?

目录 1.动态图和静态图1.1 tensorflow是静态图1.2 pytorch动态图 2. 易用性3. 编程语言4. 性能和扩展性5. 社区支持和生态系统 1.动态图和静态图 1.1 tensorflow是静态图 如上图&#xff1a; 定义计算图&#xff08;公式&#xff0c;包括定义变量x,y ,zx*y&#xff09;给公式…

Docker中安装 RabbitMQ

1、下载 RabbitMQ 镜像 下载最新版本的镜像&#xff1a; docker pull rabbitmq更多版本的镜像可以访问 Docker 官网&#xff1a;https://hub.docker.com/_/rabbitmq?tabtags 2、创建并运行 RabbitMQ 容器 启动命令&#xff1a; docker run -d -p 15672:15672 -p 5672:567…

垃圾回收小程序:环保与便捷的完美结合

一、引言 随着科技的发展&#xff0c;移动应用程序已经成为人们日常生活中不可或缺的一部分。其中&#xff0c;废品回收小程序以其独特的价值和功能&#xff0c;日益受到人们的关注和青睐。本文将探讨废品回收小程序开发的重要性、功能特点、技术实现和未来发展趋势。 二、废…

爬虫笔记(二):实战58二手房

第一&#xff1a;给大家推荐一个爬虫的网课哈&#xff0c;码起来 第二&#xff1a;今夜主题&#xff1a;通过xpath爬取58二手房的title信息&#xff0c;也就是标红的位置~ 第三&#xff1a;先分析一波title所在的位置 打开按下f12打开抓包工具&#xff0c;即可看到网站的源码…

JVM-初始JVM

什么是JVM JVM 全称是 Java Virtual Machine&#xff0c;中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件。 Java源代码执行流程如下&#xff1a; JVM的功能 1 - 解释和运行 2 - 内存管理 3 - 即时编译 解释和运行 解释…

【二】车载FrameWork添加系统服务

自定义系统服务 常见的AMS、PWS、WMS等等都是系统服务&#xff0c;运行于system_server进程&#xff0c;并且向servicemanager进程注册其Binder以便其他进程获取binder与对应的服务进行通信。为了新增自定义系统服务&#xff0c;我们可以参考AMS等原生系统服务编写如下文件&am…

Python教程:拆分多级目录的方法

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 实现多级目录差分&#xff0c;举例说明如下&#xff1a; 假设现有的目录结构如下&#xff1a;1、2、2.1、2.2、2.3、2.4、3、4、5、6、6.1、6.1.1、6.1.2、6.1.3、6…

WinSCP下载安装并实现远程SSH本地服务器上传文件

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…

【Unity学习笔记】第十一 · 动画基础(Animation、状态机、root motion、bake into pose、blendTree、大量案例)

转载引用请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/details/132081959 作者&#xff1a;CSDN|Ringleader| 如果本文对你有帮助&#xff0c;不妨点赞收藏关注一下&#xff0c;你的鼓励是我前进最大的动力&#xff01;ヾ(≧▽≦*)o 主…

#Uniapp:微信开发者工具运行与打包---打包H5---打包app

微信开发者工具运行与打包 manifest.json 添加上微信小程序AppID ** 如果点击打不开从微信开发者工具先到处本地C:\Users\fjgk-28\Desktop\huanrun\uni-demo\uni-shop\unpackage\dist\dev\mp-weixin 打开 添加上AppID试试** 微信开发者工具上传代码需要 "permission&quo…

Redis——list以及他的应用场景

介绍 &#xff1a;list 即是 链表。链表是一种非常常见的数据结构&#xff0c;特点是易于数据元素的插入和删除并且且可以灵活调整链表长度&#xff0c;但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList&#xff0c;但是 C 语言并没有实现…

文件防止泄密的措施,公司如何防止电脑泄密(防止信息泄露的6大秘籍)

在当今信息时代&#xff0c;数据安全和信息保密对于企业来说至关重要。然而&#xff0c;泄密事件时有发生&#xff0c;给企业带来巨大的损失和风险。 某泄密事件&#xff1a; 某大型企业发生了一起严重的电脑泄密事件&#xff0c;导致大量客户资料和内部战略规划被泄露。 经过…

网工每日一练(1月25日)

【说明】 某仓储企业网络拓扑结构如图1-1所示&#xff0c;该企业占地500亩。有五层办公楼1栋&#xff0c;大型仓库10栋。每栋仓库内、外部配置视频监控16台&#xff0c;共计安装视频监控160台&#xff0c;SwitchA、服务器、防火墙、管理机、RouterA等设备部署在企业办公楼一层的…

【C++入门到精通】智能指针 shared_ptr循环引用 | weak_ptr 简介及C++模拟实现 [ C++入门 ]

阅读导航 引言一、std::shared_ptr的循环引用1. 概念2. 示例分析 二、std::weak_ptr1. 简介2. weak_ptr模板类提供的成员方法3. 使用示例&#xff08;1&#xff09;weak_ptr指针的创建&#xff08;2&#xff09;完整示例&#xff08;解决上面循环引用问题&#xff09; 4. C模拟…

如何使用Flutter构建高质量的用户界面

Flutter 是一种比较流行的移动应用开发框架&#xff0c;可以让开发者使用一个代码库构建高质量的 iOS 和 Android 应用。Flutter 以其快速、美观、高度可定制等优点吸引了开发社区的广泛关注。但如何使用 Flutter 构建高质量的用户界面呢&#xff1f;下面分为以下几个部分简单的…

Matlab图像处理——谷物颗粒计数

针对目前谷物人工计数和光电计数方法存在的不足 , 提出了一种基于 Matlab 图像识别和处理技术的谷物计数方法 , 并用实例验证了其可靠性。该方法减轻了操作者劳动强度 , 弥补了人视觉的不足之处 , 提高了效率及准确率 , 为今后进一步研究奠定了必要的理论与实践基础 , 对完善“…

HarmonyOS鸿蒙应用开发 (二、应用程序包结构理解及Ability的跳转,与Android的对比)

在进行应用开发前&#xff0c;对程序的目录及包结构的理解是有必要的。如果之前有过android开发经验的&#xff0c;会发现OpenHarmony的应用开发也很简单&#xff0c;有很多概念是相似的。下面对比android分析总结下鸿蒙的应用程序包结构&#xff0c;以及鸿蒙对比android的诸多…

armv8 - GIC-V2 中断控制器

GIC起源 上一节中&#xff0c;粗略讲了hylicos上用的armv7上的一个通用中断控制器&#xff0c;其只支持60个中断源。但现代SoC上&#xff0c;中断系统正变得越来越复杂&#xff0c;旧的中断控制器已经无法胜任这些系统&#xff0c;主要体现在以下几点上&#xff1a; 中断源越…