讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

Seko
Seko

AI短剧一键生成成片

剧云
剧云

中文短剧剧本制作平台

updream

一键生成高质量推广成片

Java双向链表指定索引节点删除操作详解

风伟姑娘_1748

风伟姑娘_1748

发布时间:2025-09-13 10:23:01

|

572人浏览过

|

来源于php中文网

原创

Java双向链表指定索引节点删除操作详解

本文详细阐述了在Java中实现双向链表指定索引节点删除操作的完整方法。内容涵盖了双向链表节点和列表的泛型化设计、delete方法的参数校验、以及针对删除头节点、尾节点和中间节点等多种边界情况的精确处理。通过清晰的代码示例和关键注意事项,旨在帮助读者掌握双向链表删除操作的严谨实现,确保链表结构的完整性和数据一致性。

双向链表基础结构

在深入探讨删除操作之前,我们首先需要理解双向链表的基本构成。双向链表中的每个节点不仅指向下一个节点,还指向上一个节点,这使得从两个方向遍历链表成为可能。

节点(Node)类

双向链表的节点类通常包含数据域以及指向前后节点的引用。为了实现更强的通用性,我们采用泛型来定义节点,使其能够存储任意类型的数据。

public class Node<T> {
    T data; // 存储节点数据
    Node<T> next; // 指向下一个节点
    Node<T> previous; // 指向上一个节点

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

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

这里,T 是泛型类型参数,代表节点中存储的数据类型。

双向链表(DoublyLinkedList)类

双向链表类维护了链表的头部(head)、尾部(tail)以及当前节点数量(size)。为了保持与节点类的泛型一致性,DoublyLinkedList 也应是泛型的。如果需要对链表中的元素进行比较操作(例如排序),则泛型类型 T 需要实现 Comparable 接口。

public class DoublyLinkedList<T extends Comparable<T>> {
    protected Node<T> head;
    protected Node<T> tail;
    int size = 0;

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

    /**
     * 在链表末尾添加一个新节点
     * @param data 要添加的数据
     * @return 新添加的节点
     */
    public Node<T> append(T data) {
        Node<T> newNode = new Node<>(data);
        if (head == null) { // 链表为空时
            head = newNode;
            tail = newNode;
        } else { // 链表不为空时
            newNode.previous = tail;
            tail.next = newNode;
            tail = newNode;
        }
        size++;
        return newNode;
    }

    // toString 方法用于方便地打印链表内容
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("[%d]: ", size));
        Node<T> current = head;
        while (current != null) {
            sb.append(current.data);
            if (current.next != null) {
                sb.append(" <-> ");
            }
            current = current.next;
        }
        return sb.toString();
    }
}

核心实现:指定索引删除节点 (delete) 方法

删除双向链表中的节点比单向链表更为复杂,因为它涉及到同时更新 next 和 previous 两个指针。此外,我们需要特别处理多种边界情况,包括删除头节点、尾节点,以及链表为空或只有一个节点的情况。

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

方法签名与参数校验

delete 方法接收一个整数 location 作为参数,表示要删除节点的索引位置(从0开始)。在执行删除操作前,必须对 location 的有效性进行严格校验。

public void delete(int location) throws IllegalArgumentException {
    // 1. 参数校验:检查链表是否为空,以及索引是否越界
    if (head == null || location < 0 || location >= size) {
        throw new IllegalArgumentException("无效的索引位置或链表为空。");
    }

    // ... 后续删除逻辑
}

此校验确保了操作的安全性,避免了空指针异常和非法访问。

Blender Geometry Nodes Script Generator
Blender Geometry Nodes Script Generator

生成Blender Python (bpy)脚本,该脚本使用node_groups API和GeometryNodeTree接口程序化地创建几何节点修改器树,用于参数化3D资产生成。

下载

删除逻辑分类处理

根据 location 的值和链表当前的大小,删除操作可以分为以下几种情况:

  1. 删除链表中唯一的节点 (size == 1 && location == 0) 当链表中只有一个节点,且要删除的就是这个节点时,链表将变为空。此时,head 和 tail 都应设置为 null。

  2. 删除头节点 (location == 0 且 size > 1) 如果链表包含多个节点,删除头节点意味着将 head 指针移动到当前头节点的下一个节点。新头节点的 previous 指针必须设为 null。

  3. 删除尾节点 (location == size - 1 且 size > 1) 删除尾节点时,tail 指针需要移动到当前尾节点的前一个节点。新尾节点的 next 指针必须设为 null。

  4. 删除中间节点 (0

完整 delete 方法实现

结合上述分析,以下是 delete 方法的完整实现:

public void delete(int location) throws IllegalArgumentException {
    // 1. 参数校验
    if (head == null || location < 0 || location >= size) {
        throw new IllegalArgumentException("无效的索引位置或链表为空。");
    }

    // 2. 处理删除链表中唯一节点的情况
    if (size == 1 && location == 0) {
        head = null;
        tail = null;
    } 
    // 3. 处理删除头节点的情况 (链表有多个节点)
    else if (location == 0) {
        head = head.next; // 新的头节点是原头节点的下一个
        if (head != null) { // 确保新头节点不为空
            head.previous = null; // 新头节点的previous指向null
        }
        // 如果删除后只剩一个节点(原有两个节点),则新的head也是tail
        // 实际上,如果head.next是null,那么head就是null,tail也应该为null,这在size==1时已处理
        // 如果head.next不为null,且size-1 == 0,即原size为1,已处理
        // 如果原size为2,location=0,head变为原tail,此时head即是tail
        if (size == 2) { // 原始链表有两个节点,删除头节点后,剩下的一个节点既是头也是尾
            tail = head;
        }
    } 
    // 4. 处理删除尾节点的情况 (链表有多个节点)
    else if (location == size - 1) {
        tail = tail.previous; // 新的尾节点是原尾节点的前一个
        if (tail != null) { // 确保新尾节点不为空
            tail.next = null; // 新尾节点的next指向null
        }
        // 注意:如果原size为1,location=0,已在上面处理
        // 如果原size为2,location=1,删除尾节点后,剩下的一个节点既是头也是尾
        if (size == 2) { // 原始链表有两个节点,删除尾节点后,剩下的一个节点既是头也是尾
            head = tail; // head也指向这个唯一的节点
        }
    } 
    // 5. 处理删除中间节点的情况
    else {
        Node<T> current = head;
        // 遍历到要删除的节点
        for (int i = 0; i < location; i++) {
            current = current.next;
        }
        // current 现在指向要删除的节点
        // 调整前一个节点的next指针
        current.previous.next = current.next;
        // 调整后一个节点的previous指针
        current.next.previous = current.previous;
    }
    size--; // 链表大小减一
}

对delete方法的进一步优化和简化

上述delete方法在处理size == 2时的tail = head和head = tail逻辑有些冗余,因为head和tail的正确性会在其他分支中自然维护。更简洁和鲁棒的实现如下:

public void delete(int location) throws IllegalArgumentException {
    if (head == null || location < 0 || location >= size) {
        throw new IllegalArgumentException("无效的索引位置或链表为空。");
    }

    if (size == 1) { // 链表中只有一个节点
        head = null;
        tail = null;
    } else if (location == 0) { // 删除头节点
        head = head.next;
        head.previous = null;
    } else if (location == size - 1) { // 删除尾节点
        tail = tail.previous;
        tail.next = null;
    } else { // 删除中间节点
        Node<T> current = head;
        for (int i = 0; i < location; i++) { // 遍历到要删除的节点
            current = current.next;
        }
        // current 是要删除的节点
        current.previous.next = current.next;
        current.next.previous = current.previous;
    }
    size--; // 链表大小减一
}

这个优化后的版本更清晰地分离了逻辑,特别是当size == 1时,直接清空链表,避免了后续分支的复杂性。

示例数据类型:Student 类

为了演示双向链表的功能,我们可以创建一个简单的 Student 类作为存储在链表中的数据类型。由于 DoublyLinkedList 泛型要求 T 实现 Comparable,Student 类也需要实现此接口。

class Student implements Comparable<Student> {
    private static int counter;
    private int id;

    public Student() {
        id = ++counter; // 每次创建新学生时,ID自动递增
    }

    @Override
    public int compareTo(Student o) {
        return id - o.id; // 根据ID比较学生
    }

    @Override
    public boolean

热门AI工具

更多
火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3411

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

574

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

582

2026.02.12

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

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

549

2023.09.22

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

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

1698

2024.03.01

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

379

2026.04.23

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

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

3228

2023.10.19

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

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

5369

2025.10.17

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

40

2026.11.06

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn