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

news2024/9/24 15:16:48

目录

单向链表哨兵

初始

头插

思路

代码

尾插

思路

遍历

遍历验证头插

尾插代码

尾插测试

get

思路

代码

测试

insert

思路

代码

测试

remove

移除头结点

提问

移除指定位置

测试


单向链表哨兵

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

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

初始

public class SentinelLinkedListTest {
    
    // 头指针 指向哨兵(666是任意定义的一个值)
    private Node head = new Node(666, null);

    // 节点类      private对外隐藏细节
    @Data
    @AllArgsConstructor
    private 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.coloradmin.cn/o/1408939.html

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

相关文章

[pytorch入门] 2. tensorboard

tensorboard简介 TensorBoard 是一组用于数据可视化的工具。它包含在流行的开源机器学习库 Tensorflow 中.但是也可以独立安装&#xff0c;服务Pytorch等其他的框架 可以常常用来观察训练过程中每一阶段如何输出的 安装pip install tensorboard启动tensorboard --logdir<d…

redis-发布缓存

一.redis的发布订阅 什么 是发布和订阅 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff1a;发送者 (pub) 发送消息&#xff0c;订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。 Redis的发布和订阅 客户端订阅频道发布的消息 频道发布消息 订阅者就可…

MATLAB知识点:mode :计算众数

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章 3.4.1节 mode &#xff1a;计算众数 众数是指一…

量子网络是什么

量子网络是基于量子力学规律对量子信息进行存储、处理和传输的物理装置&#xff0c;是实现量子通讯和大规模量子计算的基础。清华大学研究团队利用同种离子的双类型量子比特编码&#xff0c;在国际上首次实现无串扰的量子网络节点&#xff0c;对未来实现量子通讯和大规模量子计…

使用Linux SDK客户端向AWS Iot发送数据

参考链接&#xff1a; https://ap-southeast-1.console.aws.amazon.com/iot/home?regionap-southeast-1#/test 此篇文章用于测试&#xff0c;使用Linux SDK客户端向AWS Iot发送数据&#xff0c;准备环境如下&#xff1a; 1、客户端环境准备 1.1 客户端操作系统 虚拟机一台…

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…

音视频基础——音视频录制及播放

音视频录制 Darren老师 当涉及音视频录制时&#xff0c;通常需要从源&#xff08;例如麦克风或摄像头&#xff09;采集音视频数据&#xff0c;并对其进行处理和编码&#xff0c;最后进行封装&#xff0c;以生成最终的音视频文件或流。以下是一般的音视频录制原理的详细步骤&am…

PHP中一些特征函数导致的漏洞总结

第一部分&#xff1a; 特征函数 接触到几个常用的函数&#xff1a; \\ \\\ md5 intval strpos in_array preg_match str_replacephp用这些函数实现过滤一些代码&#xff0c;漏洞可能有一些特性&#xff0c;利用这些特征代码进行对比&#xff1b;账号密码对比&#xff1b;强制检…

leetcode刷题(剑指offer) 105.从前序与中序遍历序列构造二叉树

105.从前序与中序遍历序列构造二叉树 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,…

【江科大】STM32:USART串口(理论部分)上

串口 全双工&#xff1a;可以进行同步通信 单端信号&#xff1a;信号线传输的就是单端信号。&#xff08;也就是与地线&#xff08;GND&#xff09;的电势差&#xff09; 缺点&#xff1a;防干扰能力差 原因&#xff1a;当信号从A点传输到B点&#xff0c;理想条件是A&#xff0…

java steam 的使用

说steam 前看下kotlin的一个写法如果用java怎么写 fun main() {// 创建一个列表val fruits listOf("Apple", "Banana", "Cherry", "Date", "Elderberry")// 使用 Sequence 进行过滤和映射操作val uppercaseFruitLengths …

qt-C++笔记之命令行编译程序,特别是使用Q_OBJECT宏包含了moc(Meta-Object Compiler)的情况

qt-C笔记之命令行编译程序&#xff0c;特别是使用Q_OBJECT宏包含了moc(Meta-Object Compiler)的情况 —— 杭州 2024-01-24 code review! 文章目录 qt-C笔记之命令行编译程序&#xff0c;特别是使用Q_OBJECT宏包含了moc(Meta-Object Compiler)的情况1.问题现象&#xff1a;q…

【华为 ICT HCIA eNSP 习题汇总】——题目集6

1、IEEE 802.11g 标准支持的最大协商速率为&#xff08;&#xff09;。 A、300Mbps B、150Mbps C、54Mbps D、1200Mbps 考点&#xff1a;无线局域网 解析&#xff1a;&#xff08;C&#xff09; IEEE 802.11系列标准如下表&#xff1a; 标准数据传输速率主要技术IEEE 802.111M…

qml与C++的交互

qml端使用C对象类型、qml端调用C函数/c端调用qml端函数、qml端发信号-连接C端槽函数、C端发信号-连接qml端函数等。 代码资源下载&#xff1a; https://download.csdn.net/download/TianYanRen111/88779433 若无法下载&#xff0c;直接拷贝以下代码测试即可。 main.cpp #incl…

Qt/QML编程之路:ListView实现横排图片列表的示例(40)

ListView列表,在QML中使用非常多,排列一个行,一个列或者一个表格,都会用到ListView。 ListView显示从内置QML类型(如ListModel和XmlListModel)创建的模型中的数据,或在C++中定义的从QAbstractItemModel或QAbstract ListModel继承的自定义模型类中的数据。 ListView有一…

计算机服务器中了mallox勒索病毒解密方案计划,勒索病毒解密措施

计算机技术的不断应用与发展&#xff0c;为企业的生产运营提供了有利条件&#xff0c;但网络安全威胁无处不在。近期&#xff0c;广西某生物制药企业的计算机服务器遭到了mallox勒索病毒攻击&#xff0c;导致企业的计算机所有重要数据被加密&#xff0c;严重影响企业的生产运营…

H5嵌入小程序适配方案

时间过去了两个多月&#xff0c;2024已经到来&#xff0c;又老了一岁。头发也掉了好多。在这两个月时间里都忙着写页面&#xff0c;感觉时间过去得很快。没有以前那么轻松了。也不是遇到了什么难点技术&#xff0c;而是接手了一个很烂得项目。能有多烂&#xff0c;一个页面发起…

gin中使用swagger生成接口文档

想要使用gin-swagger为你的代码自动生成接口文档&#xff0c;一般需要下面三个步骤&#xff1a; 按照swagger要求给接口代码添加声明式注释&#xff0c;具体参照声明式注释格式。使用swag工具扫描代码自动生成API接口文档数据使用gin-swagger渲染在线接口文档页面 第一步&…

IDEA远程服务器开发

IDEA的远程开发是在本地去操远程服务器上的代码&#xff0c;可以直接将本地代码的编译,构建,调试,运行等工作都放在远程服务器上而本地运行一个客户端远程去操作服务器上的代码,就如同我们平常写代码一样。相比于云桌面成本更低,开发效率更高。 1.首先服务器配置jdk&#xff0…

C# 将HTML网页、HTML字符串转换为PDF文件

将HTML转换为PDF可实现格式保留、可靠打印、文档归档等多种用途&#xff0c;满足不同领域和情境下的需求。本文将通过以下两个示例&#xff0c;演示如何使用第三方库Spire.PDF for .NET和QT插件在C# 中将Html 网页&#xff08;URL&#xff09;或HTML字符串转为PDF文件。 HTML转…