0

0

如何正确删除单链表中倒数第 n 个节点(含头节点更新与边界处理)

碧海醫心

碧海醫心

发布时间:2026-02-11 19:05:05

|

311人浏览过

|

来源于php中文网

原创

如何正确删除单链表中倒数第 n 个节点(含头节点更新与边界处理)

本文详解在单链表中删除倒数第 n 个节点时,为何 `n == 链表长度` 时原代码失效,并提供健壮、可维护的解决方案,重点解决头节点更新丢失、空链表/单节点异常及打印逻辑缺陷等问题。

在实现「删除链表倒数第 n 个节点」时,一个常见却极易被忽视的陷阱是:方法返回了新头节点,但调用方未将其赋值回实例字段 head。原始代码中,RemoveNthNode(Node head, int nth) 接收 head 作为参数并返回修改后的头节点,但 main 中仅调用 ll.RemoveNthNode(ll.head, 3),却未将返回值重新赋给 ll.head——导致 head 字段始终未更新,后续 PrintLL() 仍打印原始链表。

更深层的设计问题在于:该方法本应操作当前链表实例,却通过参数传入 head,不仅造成语义混淆(参数 head 遮蔽了实例字段 this.head),还强制调用方手动管理引用更新,违背面向对象封装原则。

以下是重构后的专业实现,具备完整边界处理与清晰职责划分:

public void RemoveNthNode(int nth) {
    // 空链表或仅一个节点:直接置空 head
    if (head == null || head.next == null) {
        head = null;
        return;
    }

    // 计算链表长度
    int size = 0;
    Node curNode = head;
    while (curNode != null) {
        size++;
        curNode = curNode.next;
    }

    // 边界检查:n 超出范围则不操作(也可抛异常)
    if (nth <= 0 || nth > size) {
        return;
    }

    // 情况1:删除头节点(n == size)
    if (nth == size) {
        head = head.next;
        return;
    }

    // 情况2:删除中间或尾节点
    Node prevNode = head;
    // 移动到待删节点的前驱节点(索引从1计,需走 size-nth-1 步?注意:循环条件为 i < size - nth)
    for (int i = 1; i < size - nth; i++) {
        prevNode = prevNode.next;
    }
    prevNode.next = prevNode.next.next;
}

同时,修复 PrintLL() 的逻辑缺陷:原实现对单节点链表会跳过打印(因误判 n.next == null 为终止条件)。修正后统一遍历,末尾补 "NULL" 标识结束:

ChatGPT Website Builder
ChatGPT Website Builder

ChatGPT网站生成器,AI对话快速生成网站

下载
public void PrintLL() {
    Node n = head;
    while (n != null) {
        System.out.print(n.data + " --> ");
        n = n.next;
    }
    System.out.println("NULL");
}

关键注意事项总结:
头节点必须显式更新:当删除头节点时,务必执行 head = head.next,而非仅返回;
避免参数遮蔽:移除冗余的 head 参数,直接操作实例字段,提升可读性与安全性;
全覆盖边界场景:包括 head == null、单节点、nth == 1(删尾)、nth == size(删头)、nth 超限等;
打印逻辑要鲁棒:单节点链表必须正常输出其唯一数据,不可提前退出;
命名与注释增强可维护性:如 prevNode 明确表示前驱节点,循环条件 i

最终 main 调用简洁可靠:

public static void main(String[] args) {
    Main ll = new Main();
    ll.addFirst(90);
    ll.addFirst(40);
    ll.addFirst(45); // 链表:45 → 40 → 90

    ll.PrintLL(); // 输出:45 --> 40 --> 90 --> NULL
    ll.RemoveNthNode(3); // 删除倒数第3个 → 即头节点45
    ll.PrintLL(); // 输出:40 --> 90 --> NULL
}

此方案彻底消除引用丢失风险,符合生产级链表操作规范,是理解指针操作与面向对象设计协同的关键实践。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门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语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

243

2023.09.22

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

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

685

2024.03.01

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

57

2025.11.27

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

688

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

557

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

206

2025.08.29

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

68

2026.02.11

热门下载

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

精品课程

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

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