0

0

Java双向链表:高效删除指定索引节点教程

DDD

DDD

发布时间:2025-09-13 12:45:44

|

947人浏览过

|

来源于php中文网

原创

java双向链表:高效删除指定索引节点教程

本教程详细阐述了在Java中实现双向链表(Doubly Linked List)指定索引节点删除的完整过程。内容涵盖了泛型化Node和DoublyLinkedList类、关键的删除逻辑,包括头部、尾部及中间节点的处理,以及重要的边界条件和链表状态(如head、tail、size)的维护。通过示例代码和注意事项,帮助读者构建健壮的双向链表删除功能。

1. 双向链表基础概念

双向链表是一种数据结构,其中的每个节点不仅包含数据,还包含指向下一个节点(next)和指向上一个节点(previous)的引用。这种结构允许我们从两个方向遍历链表,使得某些操作(如在给定节点前插入或删除节点)比单向链表更高效。

在Java中实现双向链表,通常需要定义两个核心类:

  • Node类:表示链表中的一个节点,包含数据、next和previous引用。
  • DoublyLinkedList类:表示整个链表,包含head(头节点)、tail(尾节点)和size(链表大小)等属性,以及各种操作方法。

为了提高代码的复用性和类型安全性,我们通常会使用泛型来定义这些类。

1.1 节点(Node)类的设计

Node类应是泛型的,以便存储任何类型的数据。它将包含一个数据字段以及指向前一个和后一个节点的引用。

立即学习Java免费学习笔记(深入)”;

class Node {
    T data; // 节点存储的数据
    Node next; // 指向下一个节点的引用
    Node previous; // 指向上一个节点的引用

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

    @Override
    public String toString() {
        return data.toString();
    }
}

1.2 双向链表(DoublyLinkedList)类的设计

DoublyLinkedList类同样应是泛型的,并且其泛型类型通常会要求实现Comparable接口,以便进行排序或其他比较操作(如果需要)。它将管理链表的head、tail和size。

public class DoublyLinkedList> {
    protected Node head; // 链表头节点
    protected Node tail; // 链表尾节点
    int size = 0; // 链表当前大小

    public DoublyLinkedList() {
        this.head = null;
        this.tail = null;
    }

    /**
     * 向链表末尾添加一个新节点。
     * @param data 要添加的数据
     * @return 新创建的节点
     */
    public Node append(T data) {
        Node newNode = new Node<>(data);
        if (head == null) {
            // 链表为空,新节点既是头也是尾
            head = newNode;
            tail = newNode;
        } else {
            // 链表不为空,新节点添加到尾部
            newNode.previous = tail;
            tail.next = newNode;
            tail = newNode; // 更新尾节点
        }
        size++;
        return newNode;
    }

    /**
     * 辅助方法:将链表内容转换为字符串,便于调试。
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("Size[%d]: ", size));
        Node current = head;
        while (current != null) {
            sb.append(current.data);
            if (current.next != null) {
                sb.append(" <-> ");
            }
            current = current.next;
        }
        return sb.toString();
    }

    // 删除方法将在下一节详细实现
    // public void delete(int location) { ... }
}

2. 实现指定索引节点删除(delete)方法

删除双向链表中的节点比单向链表稍微复杂,因为需要维护previous和next两个方向的引用。我们需要考虑多种边界情况:链表为空、删除头节点、删除尾节点以及删除中间节点。

万兴爱画
万兴爱画

万兴爱画AI绘画生成工具

下载

2.1 方法签名与初步验证

delete方法接收一个整数location作为参数,表示要删除节点的索引(0-based)。在执行任何删除操作之前,必须对location进行严格的验证。

public void delete(int location) throws IllegalArgumentException {
    // 1. 验证链表状态和索引有效性
    if (head == null || location < 0 || location >= size) {
        throw new IllegalArgumentException("Invalid deletion location or empty list.");
    }

    // 根据删除位置分为三种情况处理
    if (location == 0) {
        // 情况一:删除头节点
        deleteHead();
    } else if (location == size - 1) {
        // 情况二:删除尾节点
        deleteTail();
    } else {
        // 情况三:删除中间节点
        deleteIntermediate(location);
    }
    size--; // 成功删除后,链表大小减一
}

为了使delete方法更清晰,我们可以将其拆分为几个私有辅助方法来处理不同的删除情况。

2.2 情况一:删除头节点(location == 0)

当删除头节点时,head引用需要指向原头节点的下一个节点。同时,新头节点的previous引用必须设置为null。特别地,如果链表中只有一个节点,删除后链表将变为空,此时head和tail都应设置为null。

private void deleteHead() {
    head = head.next; // 头节点指向下一个节点
    if (head != null) {
        head.previous = null; // 新头节点的previous为null
    } else {
        // 如果head变为null,说明原链表只有一个节点,删除后链表为空
        tail = null; // 尾节点也必须设为null
    }
}

2.3 情况二:删除尾节点(location == size - 1)

当删除尾节点时,tail引用需要指向原尾节点的上一个节点。同时,新尾节点的next引用必须设置为null。

private void deleteTail() {
    tail = tail.previous; // 尾节点指向上一个节点
    if (tail != null) {
        tail.next = null; // 新尾节点的next为null
    } else {
        // 如果tail变为null,说明原链表只有一个节点,删除后链表为空
        // 此分支在delete(int location)的逻辑下不会被触发,因为location == size - 1 且 size > 1
        // 但作为独立的辅助方法,考虑此情况是好的。
        head = null; // 头节点也必须设为null
    }
}

2.4 情况三:删除中间节点(0

删除中间节点需要先遍历到待删除节点的前一个节点。然后,调整前一个节点的next引用和后一个节点的previous引用,使其跳过待删除节点。

private void deleteIntermediate(int location) {
    Node current = head;
    // 遍历到待删除节点的前一个节点
    for (int i = 0; i < location - 1; i++) {
        current = current.next;
    }

    // current 现在是待删除节点的前一个节点
    Node nodeToDelete = current.next; // 待删除节点
    Node nodeAfter = nodeToDelete.next; // 待删除节点后的节点

    current.next = nodeAfter; // 前一个节点的next指向待删除节点后的节点
    if (nodeAfter != null) {
        nodeAfter.previous = current; // 待删除节点后的节点的previous指向前一个节点
    }
    // 注意:如果nodeAfter为null,这意味着我们删除了原链表的倒数第二个节点,
    // 并且current成为了新的尾节点。然而,在这种情况下,deleteIntermediate
    // 不会直接更新tail。由于deleteIntermediate只处理中间节点,
    // 而删除倒数第二个节点严格来说不属于“中间节点”范畴,
    // 而是特殊情况,应该由deleteTail处理。
    // 但是,如果location == size - 2 (倒数第二个节点),则它仍会进入此分支。
    // 在此情况下,current是新的tail,但tail变量没有更新。
    // 修正:如果nodeAfter为null,且此节点是倒数第二个节点,那么current就是新的tail。
    if (nodeAfter == null) {
        tail = current; // 更新tail为新的尾节点
    }
}

将上述辅助方法整合到DoublyLinkedList类中,并修正`deleteIntermediate

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

237

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

539

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

21

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

28

2026.01.06

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1155

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

214

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1947

2025.12.29

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 7.9万人学习

Java 教程
Java 教程

共578课时 | 53.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号