登录
首页 >  Golang >  Go教程

Golang链表反转实现教程

时间:2026-04-11 22:06:41 324浏览 收藏

Golang反转单向链表看似简单,实则极易因忽略指针操作的原子性而断链——关键在于每次修改`cur.Next`前必须用临时变量保存原`next`节点,否则后续链路瞬间丢失;文章深入剖析了迭代法三步核心(存、改、移)、边界条件的自然处理(空链表与单节点无需额外判断)、为何Go中递归解法风险极高(栈溢出)、以及反转后原链表不可再用的本质原因,直击面试与工程实践中最常踩坑的细节,帮你真正写对、写稳、写明白。

Golang怎么用Go实现LeetCode反转链表_Golang如何用迭代法反转单向链表节点指向【入门】

Go 里反转单向链表为什么不能直接改 Next 字段就完事?

因为链表节点是值类型(ListNode 结构体),但你在遍历时操作的是指针(*ListNode)。如果只写 cur.Next = prev,不保存原 cur.Next,下一轮就会丢掉后续节点——这是最常卡住的地方。

迭代法本质是「边遍历边翻转指向」,关键在三步不丢节点:保存下一个、改当前的 Next、移动双指针。

  • 必须用临时变量存 cur.Next,否则一改 cur.Next 就断链
  • prev 初始为 nil,不是 &ListNode{},否则会多出一个空头节点
  • 循环结束时 prev 指向原链表尾,就是新链表头,直接返回它
func reverseList(head *ListNode) *ListNode {
    var prev *ListNode
    cur := head
    for cur != nil {
        next := cur.Next // 先存住,不然 cur.Next 被改后就找不到了
        cur.Next = prev
        prev = cur
        cur = next
    }
    return prev
}

LeetCode 测试用例里 head = []head = [1] 怎么不出错?

因为上面代码里 cur == nil 时循环直接跳过,prev 保持初始的 nil,空链表返回 nil 正确;单节点时循环执行一次:cur.Next 变成 nilprev 变成那个节点,返回它也正确——边界自然覆盖,不用额外 if。

  • 别手动加 if head == nil || head.Next == nil,纯属冗余
  • LeetCode 的 ListNode 定义里 ValNext 都是导出字段,可直接访问,不用 getter
  • 测试用例输入是切片,但函数接口收的是 *ListNode,构造链表逻辑在后台,你只管处理指针

为什么不用递归?递归解法在 Go 里容易栽在哪?

递归写法简洁,但 Go 默认栈空间小(2KB 左右),LeetCode 链表长度可能上万,递归深度超限直接 panic: runtime: goroutine stack exceeds 1000000000-byte limit

  • 递归每层压栈存局部变量 + 返回地址,空间复杂度 O(n),而迭代是 O(1)
  • 即使加了尾递归优化(Go 不支持),也无法避免栈溢出风险
  • 面试或线上代码,只要没明确说「必须递归」,默认选迭代更稳

reverseList 函数返回后,原链表还能用吗?

不能。这不是深拷贝,只是把原有节点的 Next 指针全翻过来了。原 head 现在是尾节点,它的 Next == nil;原来第二个节点的 Next 指向第一个,以此类推。所有节点内存没变,但逻辑顺序彻底反转。

  • 如果你还拿着旧的 head 变量去遍历,只会走到一个节点就停——它已经不是头了
  • 想保留原链表?得先深拷贝整条链,但 LeetCode 题干没要求,别给自己加戏
  • 实际工程中若需双向访问,该用双向链表,而不是反复反转单向链表

链表反转看着简单,真正写对的核心就一条:每次改 Next 前,确保下一个节点地址还在手里的变量里。其余都是围绕这个的细节取舍。

终于介绍完啦!小伙伴们,这篇关于《Golang链表反转实现教程》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>