算法 数据结构 双向环形链表 手撸环形链表 环形链表实现容器 环形链表添加修改删除获取大小 环形链表实现自定义容器 手撸容器 双向环形哨兵链表 算法(六)

news2024/11/17 23:52:08

 1. 环形链表:

                 

2. 建议先不要看我写得自己先实现下,只将Node内部类复制自己命名得容器内,

    实现方法:

                     a. add方法(添加到头部,尾部添加,指定位置添加)

                     b. get方法(获取首部,获取尾部,获取指定位置)

                     c. remove方法(删除首部,删除尾部,删除指定位置)

                     d. size方法(手动维护一个size变量,实现0(1)复杂度 )

                     e. 迭代器(实现迭代器,能够循环遍历)

     手动实现之后(每个功能只实现一种也可以),再回头参照,思考下即可!  

package com.nami.algorithm.study.day05;

import java.io.Serializable;
import java.util.Iterator;
import java.util.function.Consumer;

/**
 * 环形双向哨兵链表
 * 非线程安全
 * beyond u self and trust u self.
 *
 * @Author: lbc
 * @Date: 2023-09-01 9:07
 * @email: 594599620@qq.com
 * @Description: keep coding
 */
public class RingLinkedList<E> implements Serializable, Iterable<E>, Cloneable {

    /**
     * 容器已添加的元素
     */
    private int size = 1;

    /**
     * 哨兵节点
     */
    private Node sentinel = new Node(null, "-1", null);

    /**
     * 初始化哨兵
     */
    public RingLinkedList() {
        this.sentinel.prev = this.sentinel;
        this.sentinel.next = this.sentinel;
    }

    /**
     * 向链表添加数据
     *
     * @param element 添加的元素
     */
    public void addFirst(E element) {
        Node first = this.sentinel;
        Node next = first.next;
        Node node = new Node<>(first, element, next);
        first.next = node;
        next.prev = node;
        ++this.size;
    }

    /**
     * 向链表尾部添加数据
     *
     * @param element
     */
    public void addLast(E element) {
        Node last = this.sentinel.prev;
        Node node = new Node<>(last, element, sentinel);
        last.next = node;
        sentinel.prev = node;
        ++this.size;
    }
    
    /**
     * 获取容器指定位置的值
     *
     * @param index
     * @return
     */
    public E get(int index) {
        if (index > size - 1) {
            throw new IndexOutOfBoundsException("元素不存在");
        }
        Node next = sentinel.next;

        for (int i = 0; i < index; next = next.next, i++) {
        }
        if (sentinel == next) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }
        return (E) next.value;
    }

    /**
     * 获取指定位置节点node
     *
     * @param index
     * @return
     */
    private Node getNode(int index) {
        Node next = sentinel.next;

        for (int i = 0; i < index; next = next.next, i++) {
        }

        return next;
    }

    /**
     * 向元素指定节点添加值
     *
     * @param index
     * @param e
     */
    public void add(int index, E e) {
        if (index > size - 1) {
            throw new IndexOutOfBoundsException("元素不存在");
        }
        Node node = getNode(index);

        Node prev = node.prev;

        Node node1 = new Node(prev, e, node);
        node.prev = node1;
        prev.next = node1;
        ++this.size;
    }

    /**
     * 移除容器内第一个元素
     */
    public void removeFirst() {
        Node node = getNode(0);
        if (sentinel == node) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", 0));
        }
        Node prev = node.prev;
        Node next = node.next;
        prev.next = next;
        next.prev = prev;
        --this.size;
    }

    /**
     * 删除第一个元素
     */
    public void removeFirst0() {
        Node removed = this.sentinel.next;

        if (removed == this.sentinel) {
            throw new IndexOutOfBoundsException("容器内已无元素");
        }
        Node next = removed.next;

        this.sentinel.next = next;
        next.prev = this.sentinel;
    }

    /**
     * 移除容器内指定位置元素
     *
     * @param index
     */
    public void remove(int index) {
        if (index > size - 1) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
        }

        Node node = getNode(index);

        if (sentinel == node) {
            throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", 0));
        }

        Node prev = node.prev;

        Node next = node.next;

        prev.next = next;
        next.prev = prev;
        --this.size;
    }

    /**
     * 删除最后一个节点
     */
    public void removeLast() {
        Node prev = this.sentinel.prev;
        if (prev == this.sentinel) {
            return;
        }

        Node next = prev.next;
        Node prev0 = prev.prev;
        prev0.next = next;
        next.prev = prev0;
        --this.size;
    }

    /**
     * 获取容器大小
     *
     * @return
     */
    public int size() {
        return this.size - 1;
    }

    /**
     * 迭代器遍历
     *
     * @return
     */
    @Override
    public Iterator iterator() {
        return new NodeIterator();
    }

    /**
     * 匿名内部类
     * 内部类使用到了外部类的成员变量时,不能使用static修饰
     */
    private class NodeIterator implements Iterator {
        Node node = sentinel.next;

        @Override
        public boolean hasNext() {
            return node != sentinel;
        }

        @Override
        public Object next() {
            Object value = node.value;
            node = node.next;
            return value;
        }
    }

    /**
     * while实现
     *
     * @param consumer
     */
    public void forEach(Consumer consumer) {
        Node firstNode = this.sentinel.next;
        while (firstNode != sentinel) {
            consumer.accept(firstNode.value);
            firstNode = firstNode.next;
        }
    }

    /**
     * Node类型 节点对象
     * 二者为组合关系,所以 由外部类变为内部类,对外隐藏实现细节
     */
    private static class Node<E> {

        /**
         * 上一个节点
         */
        private Node<E> prev;

        /**
         * 值
         */
        private E value;

        /**
         * 下一个节点
         */
        private Node<E> next;


        public Node(Node<E> prev, E value, Node<E> next) {
            this.prev = prev;
            this.value = value;
            this.next = next;
        }

    }

}

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

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

相关文章

OpenCV(二十):图像卷积

1.图像卷积原理 图像卷积是一种在图像上应用卷积核的操作。卷积核是一个小的窗口矩阵&#xff0c;它通过在图像上滑动并与图像的像素进行逐元素相乘&#xff0c;然后求和来计算新图像中每个像素的值。通过滑动卷积核并在图像上进行逐像素运算&#xff0c;可以实现一系列图像处理…

Laravel 模型的关联查询 Debugbar 调试器 模型的预加载 ⑩②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; THINK PHP &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

2023高教社杯数学建模A题B题C题D题E题思路模型 国赛建模思路分享

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

Re45:读论文 GPT-1 Improving Language Understanding by Generative Pre-Training

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名&#xff1a;Improving Language Understanding by Generative Pre-Training 论文下载地址&#xff1a;https://www.mikecaptain.com/resources/pdf/GPT-1.pdf 本文是2018年OpenAI的工作&#xff0c…

智慧班牌全套源代码 智慧班牌人脸识别云平台源码

智慧校园云平台电子班牌系统源码&#xff0c;系统架构&#xff1a;Javavue2springbootMySQL elmentuiQuartzjpajwt 智慧校园建设在近年来已经形成主流&#xff0c;不少地区等级的学校都在不同程度地进行校园信息化建设优化&#xff0c;比如把人脸识别门禁应用到校门口、宿舍门口…

网站edge -- 油猴 -> IDM

一、百度网盘限速 未解决 软件&#xff1a;IDM 安装路径&#xff1a; 1.1如果&#xff1a;edge 出问题打不开其他网站&#xff0c; 解决方法&#xff1a; 以管理员的身份&#xff0c;右击载这个软件&#xff0c;就好了 1.2使用这个软件 应该是右击这个软件 以管理员的身…

VMware设置,降低Win11系统内存的使用

编辑虚拟机设置 设置处理器和内存&#xff0c;建议内存不大于4096 设置常规&#xff0c;选择客户机操作系统为Windows 高级选项&#xff0c;设置固件类型为UEFI

K8S 基础概念学习

1.K8S 通过Deployment 实现滚动发布&#xff0c;比如左边的ReplicatSet 的 pod 中 是V1版本的镜像&#xff0c;Deployment通过 再启动一个 ReplicatSet 中启动 pod中 镜像就是V2 2.每个pod 中都有一个pause 容器&#xff0c;他会连接本pod中的其他容器&#xff0c;实现互通。p…

Java 几个基本数据类型长度

对 Java 来说&#xff0c;我们通常会有下面几个基本数据类型。 需要了解的一个定义是&#xff0c;一个字节&#xff08;byte&#xff09; 是 8 位&#xff08;Bit&#xff09;。 针对 Java 的所有数据类型&#xff0c;最小的是 1 个字节&#xff0c;最多的是 8 个字节 数据长…

【Windows操作系统】Windows10升级时报VirtualBox错误导致升级失败

【背景】 明明已经卸载了VirtualBox&#xff0c;但是Win10升级时依然报错&#xff1a;VirtualBox阻止升级导致升级失败。 【分析】 说明电脑中存在VirtualBox残余&#xff0c;但是这些参与虽然能被升级程序检测到却不能在卸载VirtualBox时自动关联删除&#xff0c;需要找到…

Python实现Word、Excel、PPT批量转为PDF

今天看见了一个有意思的脚本Python批量实现Word、EXCLE、PPT转PDF文件。 因为我平时word用的比较的多&#xff0c;所以深有体会&#xff0c;具体怎么实现的我们就不讨论了&#xff0c;因为这个去学了也没什么提升&#xff0c;不然也不会当作脚本了。这里我将其放入了pyzjr库中…

如何移除 ONLYOFFICE 中的插件

如果您需要移除 ONLYOFFICE 编辑器中的某个甚至所有的插件&#xff0c;本文会向您介绍如何操作。如要详细了解&#xff0c;请阅读本文。 为什么会想移除插件 ONLYOFFICE 用户想知道如何删除插件&#xff0c;隐私问题是主要原因之一。有些插件&#xff08;如照片编辑器&#xf…

C++零碎记录(四)

6. 深拷贝与浅拷贝 ① 浅拷贝&#xff1a;简单的赋值拷贝操作。 ② 深拷贝&#xff1a;在堆区重新申请空间&#xff0c;进行拷贝操作。 ③ 浅拷贝&#xff0c;如下图所示&#xff0c;带来的问题就是堆区的内存重复释放。 ④ 深拷贝&#xff0c;如下图所示&#xff0c;在堆区…

Cyber RT学习笔记---7、Component组件认知与实践

7、Component组件认知与实践 前言 本文是对Cyber RT的学习记录,文章可能存在不严谨、不完善、有缺漏的部分&#xff0c;还请大家多多指出。 课程地址: https://apollo.baidu.com/community/course/outline/329?activeId10200 更多还请参考: [1] Apollo星火计划学习笔记——第…

Latex引用总结-图片、公式、表格、参考文献

所有的引用思路都一样&#xff0c;在定义的时候加一个标签&#xff0c;引用的时候填那个标签即可。 其中图片、公式、表格的引用代码一摸一样&#xff0c;都是label{}加ref{}&#xff0c;参考文献稍不同。 前提引用包&#xff1a; \usepackage{hyperref} \hypersetup{hypert…

CSS中如何实现文字跑马灯效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 跑马灯⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋…

mac常见问题(三) macbook键盘溅上水怎么办?

多朋友在使用mac的时候难免会发生一些小意外&#xff0c;例如说本期要为大家说的macbook键盘溅上水或者其他的液体怎么办&#xff1f;不清楚的同学赶快get这项技能吧&#xff01; 如果你不小心给你的MacBook键盘上溅了水或者其他液体&#xff0c;你需要超级快的把表面的液体清理…

远程访问公司局域网怎么设置

远程访问公司 LAN&#xff08;局域网&#xff09;计算机需要设置安全的远程访问方法&#xff0c;以确保数据的机密性和完整性。远程访问公司局域网计算机的步骤如下&#xff1a; 1、获得许可 确保您拥有远程访问公司 LAN 资源所需的权限和授权。这可能需要 IT 或网络管理员的…

SpringMVC基础入门及工作流程---全方面详细介绍

一&#xff0c;SpringMVC概念 Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂的web应用分成逻辑清晰的几部分&#xff0c;简…

【Seata】02 - Seata AT 模式 Demo 调用流程分析

文章目录 前言参考目录版本说明测试 Demo0、Demo XA / AT 模式切换1、模块说明2、调用逻辑说明3、分析流程说明4、注意事项 Seata AT 模式 Commit 调用流程分析1、调用流程图2、全局事务开启 Global Begin3、分支注册4、UndoLog5、全局事务提交 Commit6、分支提交处理 Seata AT…