【Java数据结构】链表(Linked List)-双向链表

news2025/1/25 4:26:45

双向链表(Linked List)是一种常用的数据结构,它允许在所有节点中快速添加或删除元素,并且可以有效地实现反向遍历。本篇文章将介绍双向链表的基础知识,并提供使用Java语言实现该数据结构的示例代码。


一、双向链表的基础知识

一个双向链表由多个节点组成,每个节点包含两个指针,分别指向前驱节点和后继节点。首节点的前驱节点为null,尾节点的后继节点为null。

下面是一个示意图:

null <- A <-> B <-> C <-> D -> null

 上述图中,A为首节点,D为尾节点。每个节点都有一个值域(value),这个值域可以存储任意类型的数据。在双向链表中,我们通常只需要保存首节点的引用,即可轻松访问整个链表。

二、双向链表的操作

  • 添加节点

为了在链表中添加新节点,我们需要指定插入节点的位置。假设我们要在节点B之后插入一个新节点E,则需要进行以下操作:

  1. 创建一个新节点E,并将其值域设置为目标元素。
  2. 将新节点E的前驱指针指向节点B,将新节点E的后继指针指向节点C
  3. 将节点B的后继指针指向新节点E,将节点C的前驱指针指向新节点E

下面是上述操作的示意图:

null <- A <-> B <-> E <-> C <-> D -> null
  • 删除节点

要从双向链表中删除节点,我们需要知道目标节点的位置。假设我们要删除节点C,则需要进行以下操作:

  1. 将节点C的前驱节点(即节点B)的后继指针指向节点D
  2. 将节点D的前驱指针指向节点B

下面是上述操作的示意图:

null <- A <-> B <-> E <-> D -> null
  • 遍历节点

由于双向链表中每个节点都有一个指向后继节点和前驱节点的引用,因此可以非常容易地实现正向和反向遍历。

下面是一个遍历链表并打印所有元素值的示例代码:

public class DoublyLinkedList<T> {
    private Node<T> head;
    private Node<T> tail;

    private static class Node<T> {
        private T data;
        private Node<T> prev;
        private Node<T> next;

        public Node(T data) {
            this.data = data;
            this.prev = null;
            this.next = null;
        }
    }

    public void addFirst(T data) {
        Node<T> newNode = new Node<>(data);
        if (head == null) {
            head = newNode;
            tail = newNode;
        } else {
            head.prev = newNode;
            newNode.next = head;
            head = newNode;
        }
    }

    public void addLast(T data) {
        Node<T> newNode = new Node<>(data);
        if (tail == null) {
            head = newNode;
            tail = newNode;
        } else {
            tail.next = newNode;
            newNode.prev = tail;
            tail = newNode;
        }
    }

    public void removeFirst() {
        if (head == null) {
            throw new NoSuchElementException();
        } else if (head == tail) {
            head = null;
            tail = null;
        } else {
            head.next.prev = null;
            head = head.next;
        }
    }

    public void removeLast() {
        if (tail == null) {
            throw new NoSuchElementException();
        } else if (head == tail) {
            head = null;
            tail = null;
        } else {
            tail.prev.next = null;
            tail = tail.prev;
        }
    }

    /**
    *为了实现反向遍历,我们只需要替换current.next为current.prev,同时从尾节点开始遍历即可。
    */
    public void traverse() {
        Node<T> current = head;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }
}

上述实现定义了一个 DoublyLinkedList 类,其中包含一个嵌套的 Node 类,用于表示双向链表中的节点。通过 addFirstaddLast 方法可以在链表的头部和尾部添加元素,通过 removeFirstremoveLast 方法可以删除链表中的第一个和最后一个元素。traverse方法用于遍历链表并打印所有元素值

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

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

相关文章

mysql数据库事务脏读、不可重复度、幻读详解

文章目录1 事务隔离级别2 脏读3 不可重复度3.1 解决了脏读的问题。3.2 有不可重复度的问题4 幻读4.1 没有脏读和不可重复读的问题4.2 有幻读的问题5 serializable1 事务隔离级别 read-uncommitted&#xff1a;脏读、不可重复度、幻读&#xff0c;均可出现。安全性低&#xff0…

HBase架构篇 - Hadoop家族的天之骄子HBase

HBase的基本组成结构 表&#xff08;table&#xff09; HBase 的数据存储在表中。表名是一个字符串。表由行和列组成。 行&#xff08;row&#xff09; HBase 的行由行键&#xff08;rowkey&#xff09;和 n 个列&#xff08;column&#xff09;组成。行键没有数据类型&…

《花雕学AI》06:抢先体验ChatGPT的九个国内镜像站之试用与综合评测

最近ChatGPT持续大火&#xff0c;大家们是不是在网上看到各种和ChatGPT有趣聊天的截图&#xff0c;奈何自己实力不够&#xff0c;被网络拒之门外&#xff0c;只能眼馋别人的东西。看别人在体验&#xff0c;看别人玩&#xff0c;肯定不如自己玩一把舒服的啊。 上一期&#xff0…

2.5d风格的游戏模式如何制作

文章目录一、 介绍二、 绘制瓦片地图三、 添加场景物体&#xff0c;添加碰撞器四、 创建玩家五、 创建玩家动画六、 玩家脚本七、 2d转换成2.5d八、 “Q”键向左转动视角、“E”键向右转动视角九、 下载工程文件一、 介绍 制作一个类似饥荒风格的2.5d游戏模板。 2.5D游戏是指以…

Spring之循环依赖

什么事循环依赖 很简单的定义就是就如有两个对象A类&#xff0c;B类&#xff0c;其中两个类中的属性都有对方。 A类 public class A{private B b;}B类 public class B{ private A a; }在Spring中&#xff0c;什么情况下会出现循环依赖 如果要了解循环依赖&#xff0c;首先…

基于matlab进行雷达信号模拟

一、前言此示例说明如何将基本工具箱工作流应用于以下方案&#xff1a;假设有一个工作频率为 4 GHz 的各向同性天线。假设天线位于全局坐标系的原点。有一个目标&#xff0c;其非波动雷达横截面为0.5平方米&#xff0c;最初位于&#xff08;7000&#xff0c;5000&#xff0c;0&…

Linux下使用ClamAV病毒查杀

一、介绍Clam AntiVirus 是一款 UNIX 下开源的 (GPL) 反病毒工具包&#xff0c;专为邮件网关上的电子邮件扫描而设计。该工具包提供了包含灵活且可伸缩的监控程序、命令行扫描程序以及用于自动更新数据库的高级工具在内的大量实用程序。该工具包的核心在于可用于各类场合的反病…

CompletableFuture使用详解(IT枫斗者)

CompletableFuture使用详解 简介 概述 CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口&#xff0c;并在此基础上进行了丰富的扩展&#xff0c;完美弥补了Future的局限性&#xff0c;同时CompletableFuture实现了对任务编排的能力。借助这项能力…

2023最新快速单机创建三主三从Redis集群

单机搭建Redis集群 本次采用Redis的5.0.14版本在单机centos8上搭建Redis三主三从集群. 1.创建6个文件夹 一个文件夹代表一个节点,同时也代表每个节点的端口号. 2.下载Redis文件并解压 使用命令: #下载Redis 可以将5.0.14替换成自己想要的版本 wget http://download.redis…

JavaScript面向对象编程再讲

JavaScript面向对象编程再讲 JavaScript支持的面向对象比较复杂&#xff0c;和其他编程语言又有其独特之处。本文是对以前博文 JavaScript的面向对象编程 https://blog.csdn.net/cnds123/article/details/109763357 补充。 概述 这部分是JavaScript面向对象的概括&#xff0c…

计算机网络微课堂1-3节

目录 1. TCP/TP协议​编辑 2. 3.调制解调器 4.因特网的组成 5.电路交换 6.分组交换 重要常用 7.报文交换 8.总结电路交换 报文交换和分组交换 9. 1. TCP/TP协议 2. ISP 网络提供商 ISP的三层 国际 国家 和本地 3.调制解调器 什么是调制解调器&#xff0c;它存在的…

稳压二极管工作原理、重要参数意义和典型电路参数计算

稳压二极管的工作原理&#xff1a;稳压二极管也叫稳压管&#xff0c;它在电路中一般起到稳定电压的作用&#xff0c;也可以为电路提供基准电压值。稳压二极管使用特殊工艺制造&#xff0c;这种工艺使它在反向击穿时仍然可以长时间稳定工作&#xff0c;不损坏&#xff0c;而工作…

macbook触摸板怎么按右键

苹果MacBook电脑触摸板如何右键&#xff0c;对于初次使用MacBook电脑的朋友&#xff0c;是一个小难题&#xff0c;其实MacBook电脑右键打开快捷辅助菜单的方法很简单。我们在MacBook电脑的【系统设置】—【触控板】中对触控板进行设置后可使用不同方式实现鼠标右键。 方法一&am…

形式与语言与自动机总结-----图灵机

图灵机的设计 图灵机的组成&#xff1a; 图灵机包括三部分:输入输出表带 &#xff0c;上面包括一些空格和输入字符&#xff0c;读写头可以向两个方向移动&#xff0c;每一次可以读取一个字符并对他进行改写&#xff0c;改变状态根据状态转移函数来确定。 状态转移函数: 图灵机…

【树】你真的会二叉树了嘛? --二叉树LeetCode专题Ⅳ

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

C# 文件操作

一 File\FileInfo类 在.NETFramework提供的文件操作类基本上都位于System.IO的命名空间下。操作硬盘文件常用的有两个类File\FileInfo. File类主要是通过静态方法实现的&#xff0c;FileInfo类是通过实例方法。 File类核心成员&#xff1a; FileInfo类的实例成员提供了与Fil…

Redis实现分布式锁的7种方案,及正确使用姿势!

redis学习笔记 7种方案前言 日常开发中&#xff0c;秒杀下单、抢红包等等业务场景&#xff0c;都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个方案展开&#xff0c;跟大家探讨Redis分布式锁的正确使用方式。如果有不正确的地方&#xff0c;欢迎大家指出…

c盘如何扩展分区?C盘满了这么处理就对了

案例分享&#xff1a;“c盘如何扩展分区&#xff1f;我的电脑C盘前几天都还有50GB&#xff0c;这几天发现越来越小了&#xff0c;电脑也越来越卡顿了&#xff0c;为什么我的C盘突然就满了呢&#xff1f;那么我该怎么解决这个问题&#xff1f;请求大神的帮助&#xff01;” 在使…

C++内存管理详解

大家好&#xff0c;这里是bang_bang&#xff0c;今天来分享下内存管理的知识。 目录 1.C/C内存分布 2.C内存管理方式 2.1new/delete操作内置类型 2.2new/delete操作自定义类型 3.operator new与operator delete函数 3.1operator new 3.2operator delete 4.new和delete的实现…

【C++进阶之路】初始C++语法(上)

文章目录前言一.命名空间命名冲突命名空间的使用展开命名空间作用域限定符访问作用域命名空间的合并命名空间的嵌套二.输入输出打印流插入运算符输入流提取运算符三.缺省参数全缺省半缺省跨文件缺省函数参数缺省参数的使用格式四.函数重载参数个数不同参数类型不同参数顺序不同…