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

目录

单向链表哨兵

初始

头插

思路

代码

尾插

思路

遍历

遍历验证头插

尾插代码

尾插测试

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MacOS 无法ping 通 github.com 解决方案

ping github.com 会显示请求超时&#xff1a; PING github.com (192.30.253.112): 56 data bytes Request timeout for icmp_seq 0 Request timeout for icmp_seq 1 Request timeout for icmp_seq 2 Request timeout for icmp_seq 3 Request timeout for icmp_seq 4 Request …

一文了解Ceph原理以及常见ceph指令

一、Ceph介绍 什么是分布式存储&#xff1f; 与集中式存储相反&#xff0c;分布式存储通常采用存储单元集群的形式。并且具有在集群节点之间进行数据同步和协调的机制。其目的是为了通过服务器解决大规模&#xff0c;高并发情况下的Web访问问题。 Ceph是一个统一的、分布式的存…

如何利用H5页面引导关注公众号-数灵通

随着流量获取成本的增加&#xff0c;许多企业开始寻找新的引流渠道来储存流量。H5小活动成为了一种有效的引流方式&#xff0c;并且在客户之间传递&#xff0c;形成了裂变效应。企业开始将目光转向H5网站&#xff0c;希望通过引导客户关注公众号来提升品牌影响力。 为了实现这一…

143基于matlab的2D平面桁架有限元分析

基于matlab的2D平面桁架有限元分析&#xff0c;可以改变材料参数&#xff0c;输出平面结构外形&#xff0c;各桁架应力&#xff0c;位移及作用力。可查看节点力&#xff0c;程序已调通&#xff0c;可直接运行。 143 matlab 平面桁架 有限元分析 桁架应力 (xiaohongshu.com)

温湿度传感器原理解析,温湿度传感器的应用场景有哪些?

作为常见的检测装置&#xff0c;现在已经有大大小小几十种传感器出现在我们的日常生活中。作为能够测量环境温度和湿度的传感器&#xff0c;温湿度传感器正是最常见的传感器之一&#xff0c;作为温湿度监测系统的一部分&#xff0c;被广泛应用于智慧机房、智慧楼宇、智慧农业等…

重构改善既有代码的设计-学习(三):重新组织数据

1、拆分变量&#xff08;Split Variable&#xff09; 有些变量用于保存一段冗长代码的运算结果&#xff0c;以便稍后使用。这种变量应该只被赋值一次。 如果它们被赋值超过一次&#xff0c;就意味它们在函数中承担了一个以上的责任。如果变量承担多个责任&#xff0c;它就应该被…

外贸干货!社媒营销养号全攻略:10个必须知道的养号技巧

大家都知道&#xff0c;养号已经成为任何希望在WhatsApp、Facebook、TikTok等社交媒体平台上取得成功的跨境电商和营销人员的必备技能。在本文中&#xff0c;我们将深入探讨如何高效地进行养号&#xff0c;以及如何在海外社交媒体批量养号的过程中避免封号&#xff0c;确保你的…

Jenkins全局工具配置

目录 Jenkins全局工具全局工具配置Settings 文件配置Maven配置JDK配置Git配置 Jenkins全局工具 我们在安装了Jenkins之后&#xff0c;就可以开始使用Jenkins来进行一些自动化构建发布工作&#xff0c;但是开始之前我们还需要进行全局工具的配置&#xff0c;Jenkins全局工具配置…

如何使用 NFTScan API 检索 NFT 合约地址下 Transactions 数据

对于大多数人而言&#xff0c;获取某 NFT 合约地址下的全量交易记录是十分有挑战性的&#xff0c;不仅涉及到对区块链技术的深入了解以及使用相应的工具和资源&#xff0c;还需要处理区块链上的智能合约和交易数据&#xff0c;并将其与外部数据源进行整合分析。通常&#xff0c…

【UAT阶段】测试计划分享

前面我有分享UAT阶段注意事项&#xff0c;今天跟大家分享UAT测试计划包含哪些内容&#xff1a; 希望该计划能给大家在实际项目中有所帮助&#xff1b;

求职应聘找工作,你一定会遇到的人才测评

信息时代&#xff0c;越来越多的公司在招聘时引入了人才测评机制。企业和单位希望通过人才测评在广大的应聘者中&#xff0c;找到符合自己要求的人才。虽然很多应聘者能力和简历都比较出众&#xff0c;但却在最开始的人才测评中吃了亏。有的公司很看重人才测评结果。测评就相当…

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

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

2017年认证杯SPSSPRO杯数学建模A题(第二阶段)安全的后视镜全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 A题 安全的后视镜 原题再现&#xff1a; 汽车后视镜的视野对行车安全非常重要。一般来说&#xff0c;汽车的后视镜需要有良好的视野范围&#xff0c;以便驾驶员能够全面地了解车后方的道路情况。同时&#xff0c;后视镜也要使图像的畸变尽可能…

leetcode2859-计算K置位下标对应元素的和

题目链接 2859. 计算 K 置位下标对应元素的和 - 力扣&#xff08;LeetCode&#xff09; 解题思路 枚举nums的每一个下标i&#xff1b;统计i的二进制数的1的个数&#xff1b;累加满足bit_count(i) k的nums[i]; 难点&#xff0c;如何统计二进制中1的个数&#xff1f; 例题 …

postgresql12表膨胀解决(不锁表)

查看所有数据库占用磁盘空间 SELECTpg_database.datname AS "数据库名称",pg_size_pretty(pg_database_size(pg_database.datname)) AS "磁盘占用空间" FROMpg_database;发现有个数据库占用空间过大 查询库中所有表占用空间 SELECTtable_name,pg_size_…

固态硬盘优化设置

目录 前言&#xff1a; 关闭Windows Search 禁用系统保护&#xff08;不建议&#xff09; 不建议禁用系统保护原因 关闭碎片整理 提升固态硬盘速度 开启TRIM 合理使用固态硬盘的容量 正确关机 关闭开机自启 前言&#xff1a; 电脑配备固态硬盘就能一劳永逸吗&#…

字符金字塔(C语言刷题)

个人博客主页&#xff1a;https://blog.csdn.net/2301_79293429?typeblog 专栏&#xff1a;https://blog.csdn.net/2301_79293429/category_12545690.html 题目描述 请打印输出一个字符金字塔&#xff0c;字符金字塔的特征请参考样例 输入描述: 输入一个字母&#xff0c;保…

动态规划-96.不同的二叉搜索树

给定一个整数 n&#xff0c;求以 1 ... n 为节点组成的二叉搜索树有多少种&#xff1f; 思路 二叉搜索树特性&#xff1a;左子树的节点全部小于根节点&#xff0c;右子树的节点全部大于根节点 n3&#xff0c;则1&#xff0c;2&#xff0c;3轮流当根节点。 当1为根节点时&am…

一个前端搬砖“专家“的2023年度总结

23年年中的时候&#xff0c;我跟领导进行了一次沟通&#xff0c;讨论了下我后面应该在哪些地方深入。最后我就记得领导那句&#xff1a;缺少总结。 我发现我好像确实缺少总结&#xff0c;我平时会把遇到的问题&#xff0c;感觉值得记录的写在csdn里面&#xff0c;但是都只是问…

大数据信用查询系统能查到什么呢?

在金融助贷行业&#xff0c;大数据有叫大数据信用或者网贷大数据&#xff0c;在申贷的时候&#xff0c;想必大多数人都有听说过&#xff0c;很多人因为大数据不良的原因申贷被拒过&#xff0c;那大数据信用查询系统能查到什么呢?本文就简单为大家总结几点大数据信用查询的内容…