首页 > 编程语言 >链表(双向环形链表)Java版

链表(双向环形链表)Java版

时间:2025-01-22 19:27:46浏览次数:3  
标签:Node Java 环形 value next 链表 sentinel prev

双向环形链表(一个哨兵)

双向环形链表介绍

双向环形链表是双向链表的一种特殊形式,其特点是链表的头节点和尾节点相互连接,形成一个环。相较于普通双向链表,环形结构使得链表可以在任意节点上循环遍历,非常适合某些场景,例如实现循环队列、游戏中的回合逻辑等。

双向环形链表的特点

1,环形结构:头节点的 prev 指向尾节点,尾节点的 next 指向头节点。
2,双向性:每个节点都可以通过 prev 向前,或者通过 next 向后遍历。
3,没有 null 节点:对于非空链表,遍历过程中不会遇到 null。
4,动态长度:节点数量可以随插入或删除操作动态调整。

应用场景

1,循环队列:在固定大小的数据结构中实现循环访问。
2,游戏设计:实现玩家的回合制逻辑。
3,操作系统:任务调度器中,双向环形链表可以高效管理任务队列。

代码实现

import java.util.Iterator;

//带(一个)哨兵节点
public class CircularDoublyLinked implements Iterable<Integer> {


    private static class Node {
        Node prev;
        int value;
        Node next;

        public Node(Node prev, int value, Node next) {
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    private Node sentinel = new Node(null,-1,null);//实例化

    public CircularDoublyLinked() {
        sentinel.prev = sentinel;//初始化
        sentinel.next = sentinel;//初始化
    }

    public void addFirst(int value) {//头插
        Node prev = sentinel;
        Node next = sentinel.next;
        Node inserted = new Node(prev,value,next);
        prev.next = inserted;
        next.prev = inserted;
    }

    public void removeFirst() {//头删
        Node removed = sentinel.next;
        if (removed == sentinel) {
            throw illegalIndex(0);
        }
        Node prev = sentinel;
        Node next = removed.next;
        prev.next = next;
        next.prev = prev;
    }
    public void addLast(int value) {//尾插
        Node next = sentinel;
        Node prev = sentinel.prev;
        Node inserted = new Node(prev,value,next);
        next.prev = inserted;
        prev.next = inserted;
    }
    public void removeLast() {//尾删
        Node removed = sentinel.prev;
        if (removed == sentinel) {
            throw illegalIndex(0);
        }
        Node next = sentinel;
        Node prev = sentinel.prev;
        prev.next = next;
        next.prev = prev;
    }
    public void insert(int index,int value) {//插入节点
        if (index == 0) {
            addFirst(value);
        }else {
            Node prev = findNode(index - 1);
            if (prev == null) {
                throw illegalIndex(index);
            }
            Node next = prev.next;
            Node inserted = new Node(prev,value,next);
            prev.next = inserted;
            next.prev = inserted;
        }

    }
    private Node findNode(int index){//寻找节点
        int i = 0;
        Node p = sentinel.next;
        while (p != sentinel) {
            if (i == index) {
                return p;
            }
            i++;
            p = p.next;
        }
        return null;
    }

    public void removeByValue(int value) {//根据值来删除
        Node removed = findByValue(value);
        if (removed == null) {
            return;
        }
        Node prev = removed.prev;
        Node next = removed.next;
        prev.next = next;
        next.prev = prev;
    }
    private Node findByValue(int value) {//返回相应值的节点
        Node p = sentinel.next;
        while (p != sentinel) {
            if (p.value == value) {
                return p;
            }
            p = p.next;
        }
        return null;
    }






    @Override
    public Iterator<Integer> iterator() {//迭代器
        return new Iterator<Integer>() {
            Node p = sentinel.next;
            @Override
            public boolean hasNext() {
                return p != sentinel;
            }

            @Override
            public Integer next() {
                int value = p.value;
                p = p.next;
                return value;
            }
        };
    }


    public void showList() {//遍历链表
        if (sentinel.next == sentinel) {
            System.out.println("链表为空");
            return;
        }
        System.out.print("链表遍历: ");
        forEach(integer -> {
            System.out.print(integer + " ");
        });
        System.out.println("");

    }
    private IllegalArgumentException illegalIndex(int index) {//异常信息

        return new IllegalArgumentException(
                String.format("索引:Index[%d],不合法 %n", index));
    }
}

标签:Node,Java,环形,value,next,链表,sentinel,prev
From: https://blog.csdn.net/dwfwhh/article/details/145309463

相关文章

  • 链表(双向链表)Java版
    双向链表(有哨兵节点)双向链表介绍双向链表的特点应用场景代码解析Java代码双向链表介绍双向链表(DoublyLinkedList)是一种链式存储结构,每个节点不仅包含数据,还包含两个指针,分别指向前驱节点和后继节点。它相比单向链表有更高的灵活性,因为可以从任意节点向前或向后遍历......
  • 基于java web的社区人员流动管理系统的设计与实现-毕业设计源码19467
    目 录1绪论1.1研究背景与意义1.2国内外研究现状1.3论文结构与章节安排2 系统分析2.1可行性分析2.1.1技术可行性分析2.1.2经济可行性分析2.1.3法律可行性分析2.2系统功能分析2.2.1功能性分析2.2.2非功能性分析2.3系统用例分析2.4系......
  • JavaSE基础笔记
    Java基础笔记一、流程控制(一)Scanner输入1、next()读取到空白就会自动将其去掉,next()不能得到带有空格的字符串hasNext()可以判断是否还有输入的数据packagecom.TEST.Test01;importjava.util.Scanner;publicclassTest01{publicstaticvoidmain(String[......
  • java 中的匿名内部类
    在Java中,匿名内部类是一种没有名称的内部类,通常用于简化代码,尤其是在实现接口或继承类时,只需要一个简单的实现。匿名内部类允许你在创建类的同时实例化它,通常用于简化代码的书写。工作原理匿名内部类是在你需要使用接口或抽象类的实现时定义和实例化的。它们在使用时定义在方法......
  • 【转】[JavaScript] import 和 export 的用法
    转自:kimi.ai在JavaScript中,import和export是ES6(ECMAScript2015)引入的模块化语法,用于在不同的文件或模块之间共享代码。它们使得代码更加模块化、可维护,并且可以避免全局变量的污染。以下是import和export的基本用法和一些常见场景。1. export 的用法export用于......
  • Java 变量和数据类型
    目录变量数据类型数据类型分类基本数据类型包装类装箱和拆箱手动拆装箱:自动拆装箱:包装类的特点总结变量的定义格式注变量变量:常量是固定不变的数据,那么在程序中可以变化的量称为变量。数学中,可以使用字母代替数字运算,例如x=1+5或者6=x+5。程序中,可以使用字母保存数字......
  • Java 并发
    目录线程多线程原理多线程的常用方法Thread类创建线程四种方式继承Thread类实现Runnable接口实现Callable接口FutureTask使用匿名内部类方式Thread和Runnable的区别Runnable和Callable的区别线程的run()和start()有什么区别?线程安全线程安全线程同步同步代码块同......
  • java流之Stream
    java流之Stream流:在现实中有移动,传播,延绵不绝,其有难寻其源,难觅其踪,变约莫测等特点。stream:是jdk8中新增的api成员,是对容器对象功能的增强,借助于同样是新出现的Lambda表达式,提供了方便、简洁、高效、链式等方式处理集合容器,以获取自己需要的结果。java中的流stream与现实中的流......
  • Javase--基础语法上
    Javase--基础语法注释packageMistiest.com.cnblogs.comment;/***这里介绍注释的基本语法,这个是文本注释,一般写在方法的最前面*/publicclasscomment{publicstaticvoidmain(String[]args){//这是单行注释/*这是多行注释......
  • JavaScript 自定义获取当前日期和时间的函数
    JavaScript自定义获取当前日期和时间的函数 /***获取当前的日期和时间*格式为yyyy-MM-ddHH:mm:ss.SSS*/functiongetNowDateTime(){varnow=newDate,year=now.getFullYear(),month=now.getMonth()+1......