跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

单链表综合练习:删除指定节点、反转与查找中间节点

单链表是数据结构中的基础结构,通过三个经典案例讲解其核心操作。首先演示如何通过尾插法构建新链表来删除特定值的节点;接着利用三指针技巧原地反转链表,注意空指针处理;最后使用快慢指针高效定位中间节点,避免偶数长度时的越界风险。代码均基于 C 语言实现,适合夯实指针基础。

DataScient发布于 2026/3/30更新于 2026/10/2489 浏览
单链表综合练习:删除指定节点、反转与查找中间节点

单链表核心操作实战

链表是 C 语言指针操作的经典场景,也是数据结构面试中的高频考点。掌握链表的增删改查,尤其是涉及指针指向变更的逻辑,对理解内存管理至关重要。下面我们通过三个典型题目,拆解链表操作的核心思路。

一、删除链表中等于给定值 val 的所有节点

思路解析

这道题的关键在于如何处理头结点可能也需要被删除的情况。如果直接遍历原链表修改 next 指针,需要额外处理 head 为空或 head 本身即为目标值的情况。

这里采用一种更稳健的方法:构建一个新链表。遍历原链表,将不等于 val 的节点依次尾插到新链表中。这样既避免了复杂的空指针判断,逻辑也相对清晰。需要注意的是,新链表构建完成后,务必将尾节点的 next 置为 NULL,防止形成环。

算法原理示意图

参考实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;

struct ListNode* removeElements(struct ListNode* head, int val) {
    ListNode* newhead = NULL;
    ListNode* newtail = NULL;
    ListNode* pcur = head;

    while (pcur) {
        if (pcur->val != val) {
            if (newhead == NULL) {
                // 链表为空,初始化头尾指针
                newhead = newtail = pcur;
            } else {
                // 尾插法连接节点
                newtail->next = pcur;
                newtail = pcur;
            }
        }
        pcur = pcur->next;
    }

    // 重要:断开新链表尾部,避免野指针
    if (newtail) newtail->next = NULL;
    return newhead;
}

二、反转链表

思路解析

反转链表是考察指针操作熟练度的经典题。核心思想是改变每个节点的 next 指向,使其指向前一个节点。为了在断链的同时不丢失后续节点,我们需要三个指针:

  • prev(前驱):初始化为 NULL,最终将成为新的头结点。
  • curr(当前):初始化为 head,负责遍历和修改指向。
  • next(后继):暂存 curr 的下一个节点,防止断链后无法继续遍历。
  • 循环中,先将 curr 的 next 指向 prev,然后三者同步向后移动。注意处理空链表的情况,直接返回即可。

    反转过程图解

    参考实现

    struct ListNode* reverseList(struct ListNode* head) {
        // 边界检查:空链表直接返回
        if (head == NULL) return head;
    
        ListNode* n1 = NULL;      // 前驱节点
        ListNode* n2 = head;      // 当前节点
        ListNode* n3 = head->next; // 后继节点
    
        while (n2) {
            n2->next = n1;        // 反转指针方向
            n1 = n2;              // 前驱后移
            n2 = n3;              // 当前后移
            if (n3) n3 = n3->next; // 后继后移
        }
        return n1; // n1 即为新的头结点
    }
    

    三、链表中间节点

    思路解析

    寻找中间节点最优雅的方案是使用快慢指针。定义两个指针 slow 和 fast,初始都指向头结点。slow 每次走一步,fast 每次走两步。当 fast 到达链表末尾时,slow 恰好位于中间位置。

    这里有一个细节需要注意:循环条件应写为 while(fast && fast->next)。如果只写 fast,在偶数长度链表中,fast 可能会走到 NULL 后再访问 fast->next 导致空指针解引用异常。此外,对于偶数个节点,通常返回第二个中间节点,该逻辑天然符合上述循环条件。

    快慢指针示意

    参考实现

    struct ListNode* middleNode(struct ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
    
        // 确保 fast 和 fast->next 均有效
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
    

    以上三个题目涵盖了链表操作中'删除'、'反转'和'遍历定位'的基础模式。在实际开发中,遇到类似结构问题时,不妨先画图理清指针关系,再动手编码,能有效减少空指针错误。建议结合图示反复调试代码,加深理解。

    目录

    1. 单链表核心操作实战
    2. 一、删除链表中等于给定值 val 的所有节点
    3. 思路解析
    4. 参考实现
    5. 二、反转链表
    6. 思路解析
    7. 参考实现
    8. 三、链表中间节点
    9. 思路解析
    10. 参考实现

    更多推荐文章

    查看全部
    • Ollama 快速部署大模型:Windows/Linux/Mac 通用教程
    • STC15 系列单片机:存储器与特殊功能寄存器
    • ERNIE-4.5-0.3B:文心一言轻量级大模型的产业落地新范式
    • DVC 数据版本控制:像 Git 一样管理数据和模型
    • uniapp 判断运行设备类型(安卓、苹果、鸿蒙、微信小程序、H5)
    • 网络安全岗位常见面试题与实战指南
    • Python Flask Vue 图书借阅管理信息系统设计与实现
    • 归并排序实战:计算右侧小于当前元素个数与翻转对
    • Z-Image-Turbo 一键部署与使用指南
    • Vitis 从零实现 AI 模型 FPGA 部署实战
    • 仿 Mudou 库 one thread per loop 式并发服务器实现:边缘测试与性能测试
    • 12 大主流 AI 前端组件库盘点:Ant Design X ChatUI 等
    • 《Agent Runtime 工程化》第二章 TypeScript / Node Runtime 基础:2.4 子进程执行器:Agent 的危险地带
    • Harness Engineering:给 AI 套上缰绳的工程学
    • Visual C++ Redistributable 运行库缺失与损坏修复指南
    • Midjourney 角色一致性控制实战:双人物同框生成指南
    • 人工智能、机器学习与深度学习的区别及关系
    • C++ 跳表核心原理与性能解析
    • Python 爬虫实现豆瓣电影数据采集实战
    • Redis Hash 核心操作与 C++ 实践

    相关免费在线工具

    • 加密/解密文本

      使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

    • Gemini 图片去水印

      基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

    • Markdown转HTML

      将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

    • HTML转Markdown

      将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online