news 2026/8/14 13:35:45

单链表专题(一)-应用篇:三道经典题吃透删除、反转与快慢指针

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
单链表专题(一)-应用篇:三道经典题吃透删除、反转与快慢指针

单链表是数据结构课程的第一个核心线性结构,也是算法入门与校招面试的必练内容。不同于数组支持下标随机访问,单链表依靠next指针串联节点,所有操作都围绕「指针指向修改」展开,极其考验对边界场景的把控能力。

本文以三道最经典的单链表应用题为例,从思路推导到代码实现、从易错点复盘到算法思想升华,系统梳理单链表的核心操作与解题套路。

一、单链表基础回顾

单链表的每个节点由「数据域」和「后继指针域」组成,只能从头节点出发单向遍历,无法反向访问,也不能直接通过下标定位节点。 C 语言中节点的标准定义如下:

struct ListNode { int val; struct ListNode *next; }; typedef struct ListNode ListNode;

单链表操作的三大核心特点:

  1. 已知前驱节点时,插入 / 删除节点的时间复杂度为 O (1),只需修改指针指向,无需移动元素。
  2. 访问任意节点必须从头遍历,时间复杂度 O (n),不支持随机访问。
  3. 头节点可能发生变化(如删除头节点、反转链表),是最容易出错的边界点。

在开始刷题前,先记住单链表的通用避坑原则:

  • 访问ptr->valptr->next前,必须确保ptr不为NULL,否则会触发空指针崩溃。
  • 修改节点的next指针前,先保存原后继节点,避免链表断裂、遍历中断。
  • 重新拼接链表后,必须确保最终尾节点的next = NULL,标记链表结束。

二、经典题逐题精讲

2.1 移除链表元素(LeetCode 203)

题目描述

给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val == val的节点,并返回新的头节点。

题意分析

这道题是单链表「删除操作」的入门题,核心难点不在删除逻辑本身,而在边界场景:

  • 头节点本身就是要删除的节点,新头节点会变化
  • 链表尾部是要删除的节点
  • 链表所有节点都需要删除,最终返回空链表
  • 链表本身就是空链表

解法一:尾插法构建新链表

这是最符合直觉的思路:不直接在原链表上做剪断删除,而是遍历原链表,把值不等于val的合法节点,按原有顺序重新拼接成一个新链表。

完整代码

struct ListNode* removeElements(struct ListNode* head, int val) { // 新链表的头、尾指针,初始为空 ListNode *newHead, *newTail; newHead = newTail = NULL; ListNode *pcur = head; // 遍历原链表 while(pcur) { if(pcur->val != val) { // 当前节点需要保留,尾插到新链表 if(newHead == NULL) { // 新链表为空,第一个节点同时是头和尾 newHead = newTail = pcur; } else { // 接到尾部,尾指针后移 newTail->next = pcur; newTail = newTail->next; } } pcur = pcur->next; } // 关键收尾:新链表非空时,尾节点next置空 if(newTail != NULL) { newTail->next = NULL; } return newHead; }

思路细节拆解

  1. 天然解决头节点删除问题:第一个被保留的节点自然成为新头,无需单独判断原头节点是否要删。
  2. 尾节点置空是必写步骤:如果原链表尾部是要删除的节点,新链表最后一个节点的next仍会指向原链表的无效节点,必须手动置空标记链表结束。
  3. 空指针防护:如果所有节点都被删除,newTail仍为NULL,必须先判断非空再访问next

解法二:虚拟头节点原地删除

这是链表删除题的工业级标准写法,核心是在原链表头部加一个「哨兵节点(dummy)」,让所有待删除节点都成为 “某个节点的后继”,删除逻辑完全统一。

完整代码

struct ListNode* removeElements(struct ListNode* head, int val) { // 创建虚拟头节点,next指向原链表头 ListNode dummy; dummy.next = head; ListNode* cur = &dummy; while (cur->next != NULL) { if (cur->next->val == val) { // 下一个节点要删除:直接跳过该节点 cur->next = cur->next->next; } else { // 下一个节点保留:指针后移 cur = cur->next; } } return dummy.next; }

这种写法的优势非常明显:无需单独处理头节点,无需手动置空尾节点,代码更简洁,边界场景全部自动兼容。


2.2 反转链表(LeetCode 206)

题目描述

给你单链表的头节点head,请你反转链表,并返回反转后的链表。

题意分析

反转链表的本质,是把每个节点的next指针从「指向后继」改为「指向前驱」。最大的难点是:直接修改当前节点的next会丢失后继节点,导致链表断裂、遍历无法继续。

解法:三指针迭代原地反转

这是面试的标准最优解,空间复杂度 O (1),全程只通过三个指针配合,逐个翻转节点指向。

完整代码

struct ListNode* reverseList(struct ListNode* head) { if(head == NULL) { return head; } ListNode *n1, *n2, *n3; n1 = NULL; // 前驱节点 n2 = head; // 当前节点 n3 = head->next; // 后继节点(提前保存,防止断链) while(n2) { // 翻转当前节点的指向 n2->next = n1; // 三个指针整体后移 n1 = n2; n2 = n3; if(n3) { n3 = n3->next; } } return n1; }

三个指针的分工

  • n1:记录当前节点的前驱节点,也就是反转后当前节点要指向的目标。初始为NULL,因为原头节点反转后会变成尾节点。
  • n2:当前正在处理的节点,从原头节点开始逐个向后遍历。
  • n3:提前保存当前节点的后继节点,相当于 “备份后路”。修改n2->next后原后继会丢失,必须提前存下来。

执行流程模拟(以 1→2→3→NULL 为例)

  1. 初始:n1=NULLn2=1n3=2
  2. 第一轮:节点 1 的 next 指向 NULL;n1 移到 1,n2 移到 2,n3 移到 3
  3. 第二轮:节点 2 的 next 指向 1;n1 移到 2,n2 移到 3,n3 移到 NULL
  4. 第三轮:节点 3 的 next 指向 2;n1 移到 3,n2 移到 NULL,循环结束
  5. 此时 n1 指向原链表最后一个节点,也就是反转后的新头节点,直接返回即可。

拓展:递归解法

递归写法代码更简洁,核心思想是 “先递归到链表尾部,再从后往前逐个翻转”。

struct ListNode* reverseList(struct ListNode* head) { // 终止条件:空链表或只有一个节点,无需反转 if (head == NULL || head->next == NULL) { return head; } // 先反转子链表,得到子链表的新头 ListNode* newHead = reverseList(head->next); // 把当前节点接到子链表尾部 head->next->next = head; // 当前节点变为尾节点,置空防止成环 head->next = NULL; return newHead; }

2.3 链表的中间结点(LeetCode 876)

题目描述

给你单链表的头结点head,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

题意分析

单链表不能随机访问,朴素做法是「先遍历一遍统计长度,再从头走长度的一半」,但需要两次遍历。 这道题的最优解是快慢指针(龟兔赛跑算法),只需一次遍历就能找到中点,也是单链表最经典的算法思想之一。

核心算法:快慢指针

利用两个指针的速度差实现定位:

  • 慢指针slow:一次走 1 步
  • 快指针fast:一次走 2 步

因为快指针速度是慢指针的 2 倍,当快指针走到链表末尾时,慢指针走过的路程刚好是一半,正好停在中间位置。

完整代码

struct ListNode* middleNode(struct ListNode* head) { ListNode *Fast, *Slow; Fast = Slow = head; while(Fast && Fast->next) { Slow = Slow->next; Fast = Fast->next->next; } return Slow; }

循环条件深度解析

while(Fast && Fast->next)是这道题最核心的细节,有两个关键点:

  1. 顺序不能反:利用 C 语言的短路求值特性,先判断Fast是否为空;如果Fast已经是 NULL,程序不会再访问Fast->next,完美避免空指针崩溃。
  2. 决定了中点落点:这个条件会让快指针最终停在「最后一个节点的下一位(NULL)」,因此偶数长度时,慢指针正好落在第二个中间节点上,完全符合题目要求。

场景验证

  • 奇数长度(5 个节点):快指针停在最后一个节点,慢指针停在第 3 个节点(正中间)
  • 偶数长度(6 个节点):快指针停在 NULL,慢指针停在第 4 个节点(第二个中间节点)

拓展与延伸

如果题目要求返回第一个中间节点,只需修改循环条件:

while(Fast->next && Fast->next->next)

快慢指针的应用远不止找中点,它还是解决「判断链表是否有环」「找环的入口节点」「找链表倒数第 k 个节点」等经典题的核心思想,是单链表必须掌握的算法套路。


三、单链表解题通用方法论

做完这三道题,我们可以提炼出单链表应用题的通用解题框架:

  1. 头节点变化的两种处理方案只要题目可能修改头节点(删除、反转、排序),要么用「新链表 + 新头指针」,要么用「虚拟头节点」,两种思路都能避免单独处理头节点的冗余逻辑。

  2. 指针修改的铁则凡是要修改节点的next指针,先问自己一句:修改之后,原后继节点还找得到吗?如果找不到,就必须先用临时指针保存下来,防止断链。

  3. 边界场景必测清单写完代码后,务必用这几个场景验证:空链表、单个节点、两个节点、目标节点在头部、目标节点在尾部、所有节点都符合删除条件。能覆盖这几个场景,代码基本不会出大问题。

  4. 画图辅助调试链表题的指针跳转很抽象,遇到逻辑混乱时,在纸上画出节点和箭头,手动模拟每一步指针的移动,比盯着代码死想高效得多。

写在最后

这三道题是单链表的「基石题」,覆盖了删除、反转、快慢指针三大核心考点。把这三道题的每一行代码、每一个边界条件都吃透,再去学习合并有序链表、环形链表、相交链表等进阶题目时,就会发现核心逻辑都是相通的。

数据结构的学习没有捷径,多写、多画、多踩坑、多复盘,慢慢就能建立起对指针操作的直觉。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/14 13:35:43

网站建设所需材料:新手避坑指南与企业必备清单深度解析

今天咱们不聊那些虚头巴脑的技术原理,也不扯什么高大上的互联网思维,就单纯从一个做过几十个企业官网、也帮无数初创团队踩过坑的过来人角度,聊聊网站建设之前到底需要准备什么东西。很多人一听“建站”,第一反应就是找家公司花几万块钱,把网站搬过去就行。但现实往往不是…

作者头像 李华
网站建设 2026/8/14 13:35:42

Axure 全版本汉化指南:9、10、11 中文界面一次到位

Axure 全版本汉化指南:9、10、11 中文界面一次到位 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 周四下午两点&…

作者头像 李华
网站建设 2026/8/14 13:33:29

成都医院网站建设:打破信息孤岛,重塑医患信任的数字桥梁

在这个互联网早已渗透到我们生活每一个角落的今天,去医院看病对于很多人来说,已经不仅仅是一次身体的检查或治疗,更是一场心理的博弈。当你拖着疲惫的身体,或是带着家人的担忧走进医院大门之前,你最先接触的往往不是医生温润的话语,也不是导诊台热情的指引,而是手机屏幕…

作者头像 李华
网站建设 2026/8/14 13:32:32

从一张照片到一件浮雕:用ImageToSTL完成图片转STL的全过程

从一张照片到一件浮雕:用ImageToSTL完成图片转STL的全过程 【免费下载链接】ImageToSTL This tool allows you to easily convert any image into a 3D print-ready STL model. The surface of the model will display the image when illuminated from the left si…

作者头像 李华
网站建设 2026/8/14 13:32:16

怎么建设免费网站从零开始打造个人品牌,低成本启动你的数字梦想

大家好,我是你们的老朋友,一个在IT圈摸爬滚打多年,同时也热衷于帮身边朋友解决“上网”问题的折腾派。今天咱们不聊那些高大上、烧钱的企业级解决方案,也不谈什么复杂的服务器运维和代码重构。今天我们要聊的话题特别实在,甚至有点“接地气”,就是:怎么建设免费网站。我…

作者头像 李华
网站建设 2026/8/14 13:31:47

别被忽悠了!揭秘靠谱山西网站建设公司背后的真相与干货

做企业的人都懂,现在的市场竞争有多卷。以前我们觉得,有个办公地点、有个名片,生意就能做。现在呢?客户打开手机搜一下,你的网站打开速度超过三秒,人家转头就走了;界面丑得没眼看,客户觉得你这公司不专业,连你的电话都不想打。所以,很多老板现在都在发愁,到底该怎么…

作者头像 李华