---
title: 用火车车厢翻转的趣味比喻，深入浅出地讲解链表反转的核心思路与Python实现
created: 2026-03-16
updated: 2026-03-16
type: summary
tags: ["algorithm", "list", "notes", "python", "telegram"]
external: http://go/ui/posts/2187/
status: inbox
---

# 用初中生能懂的方式拆解「反转链表」

## 🧩 题目本质：像翻转一列火车车厢

想象一列火车车厢（链表）：
```
车头 → [1] → [2] → [3] → [4] → [5] → 终点
```

你要做的是让火车**掉头行驶**：
```
车头 → [5] → [4] → [3] → [2] → [1] → 终点
```

但有个问题：每节车厢（节点）只能看到**下一节**车厢，看不到前一节。怎么翻转呢？

## 🔍 关键思路：三个手指头工作法

我们可以用三个"临时小纸条"（变量）来帮忙：

1. **prev**（前一个）：记录"已经翻转好的部分"的最后一节车厢
2. **curr**（当前）：正在处理的车厢
3. **next_temp**（下一个）：先把下一节车厢的位置记下来，免得丢失

### 图解每一步：

**初始状态：**
```
prev = None（还没有翻转好的部分）
curr = 车头（1号车厢）

车头 → [1] → [2] → [3] → [4] → [5]
       ↑
      curr
```

**第一步：**
```
next_temp = curr.next  // 先记下2号车厢的位置
curr.next = prev       // 让1号车厢指向None（断开原来的连接）
prev = curr            // prev现在是1号车厢
curr = next_temp       // curr移动到2号车厢

结果：
[1] → None
 prev
[2] → [3] → [4] → [5]
 curr
```

**第二步：**
```
next_temp = curr.next  // 记下3号车厢
curr.next = prev       // 让2号车厢指向1号车厢
prev = curr            // prev现在是2号车厢
curr = next_temp       // curr移动到3号车厢

结果：
[2] → [1] → None
 prev
[3] → [4] → [5]
 curr
```

**重复这个过程，直到curr变成None...**

**最终：**
```
prev = [5] → [4] → [3] → [2] → [1] → None
（这就是翻转后的链表头！）
```

## 🐍 Python代码实现

```python
# 先定义链表节点（就像定义一节车厢的结构）
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val      # 车厢里装的东西（数据）
        self.next = next    # 指向下一节车厢的绳子（指针）

# 解决方案
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        # 初始化三个"小纸条"
        prev = None        # 已经翻转好的部分，刚开始是空的
        curr = head        # 从火车头开始
        
        # 开始逐节翻转
        while curr:
            # 第一步：先记下下一节车厢的位置
            next_temp = curr.next
            
            # 第二步：让当前车厢掉头（指向已经翻转好的部分）
            curr.next = prev
            
            # 第三步：移动"前一个"和"当前"指针
            prev = curr
            curr = next_temp
        
        # 当curr变成None时，prev就是新的火车头！
        return prev
```

## 📝 分步验证（手动模拟）

假设链表是：`1 → 2 → 3`

| 步骤 | prev | curr | next_temp | 动作 | 链表状态 |
|------|------|------|-----------|------|----------|
| 开始 | None | 1 | - | 初始化 | 1→2→3 |
| 1 | None | 1 | 2 | 1.next=None, prev=1, curr=2 | **1**→None, 2→3 |
| 2 | 1 | 2 | 3 | 2.next=1, prev=2, curr=3 | **2→1**→None, 3 |
| 3 | 2 | 3 | None | 3.next=2, prev=3, curr=None | **3→2→1**→None |
| 结束 | 3 | None | - | 返回prev=3 | 翻转完成！ |

## ⚠️ 初中生常犯的错误

1. **忘记保存next_temp**：如果直接 `curr.next = prev`，就找不到原来的下一节车厢了！
2. **循环条件错误**：应该是 `while curr`，不是 `while curr.next`
3. **返回错误变量**：最后应该返回 `prev`，不是 `curr`（curr已经是None了）

## 🧠 记忆口诀

> "记下后一个，断开连前一个，移移移，直到没得移"

## 🚀 进阶思考（有余力的同学）

1. **递归解法**：如果火车太长，可以"先让后面的车厢翻转完，再把自己接上去"
2. **边界情况**：空链表（没有车厢）、只有一个车厢的情况
3. **时间复杂度**：O(n)，每个车厢只被处理一次，就像数车厢一样快

## ✨ 总结

反转链表的核心就是**改变每个节点的指向**：
- 从"指向下一节"变成"指向前一节"
- 用三个临时变量确保不会"丢失"车厢
- 就像接力赛一样，一节一节完成翻转

试着用纸笔画出这个过程，你会理解得更清楚！如果某个步骤卡住了，可以随时问我。
