大家好,我是Tony Bai。
欢迎来到我们的专栏 《AI 时代软件工程师的算法图谱》的第四讲。
前三讲我们处理的都是数组(Slice)和字符串,它们在内存中是连续的,访问速度极快。但今天,我们要进入一个“碎片化”的世界——链表(Linked List)。
在现代高级编程(如 Python/Java/Go 业务层)中,链表似乎不如数组常用。但在操作系统内核、内存分配器(Malloc)、Redis 底层(Ziplist/Quicklist)这些硬核领域,链表是绝对的王者。它不需要连续内存,插入删除极其灵活,是连接离散数据的纽带。
对于 Go 工程师来说,理解链表不仅是为了刷题,更是为了理解container/list标准库,甚至是 Go Runtime 内部的mspan链表管理机制。
今天,我们将通过指针的“穿针引线”,体验内存操纵的艺术。
模式解构:指针的“断与连”
链表的核心在于节点(Node)与指针(Pointer/Reference)。每个节点包含数据和指向下一个节点的指针。
操作链表时,最容易犯的错误就是“断链”(丢失了节点的引用)和“成环”(死循环)。为了驾驭它,我们需要掌握几个核心模式:
虚拟头节点 (Dummy Head)
痛点:处理头节点(Head)非常麻烦,因为头节点没有“前驱节点”。删除头节点和删除中间节点的逻辑不一样。
解法:创建一个
dummy节点指向head。这样所有业务节点都有了前驱,逻辑统一。场景:几乎所有链表题目(删除、合并、反转)。