蛇形遍历指按行交替方向访问矩阵:第0行从左到右,第1行从右到左,依此类推,像蛇爬行折返;而普通遍历(如常规行优先)始终单向扫描。

什么是蛇形遍历,和普通遍历有啥区别
蛇形遍历指按行扫描时方向交替:第 0 行从左到右,第 1 行从右到左,第 2 行又从左到右……像蛇爬行一样折返。它不改变数组存储结构,只改变访问顺序。常见于打印矩阵、生成螺旋/蛇形索引、算法题预处理等场景。
容易踩的坑是直接用 for (int i = 0; i 套两层循环硬写方向逻辑,结果边界错位或越界——尤其当行数为奇数、列数不固定时,<code>i % 2 == 0 判断方向看似合理,但列下标起始/终止值没同步调整就会漏元素或重复访问。
用 std::vector<:vector>> 实现最稳的蛇形遍历
C++ 中推荐用 std::vector 而非 C 风格二维数组(如 int arr[5][5]),因为尺寸可变、内存安全,且能自然支持每行独立翻转。核心思路是:先按行读取,对偶数索引行(i % 2 == 0)保持原序,对奇数索引行调用 std::reverse。
- 假设矩阵为
matrix,类型是std::vector<:vector>></:vector>,非空判断必须做:if (matrix.empty() || matrix[0].empty()) return; - 遍历时用
size_t i = 0而非int i,避免与matrix.size()(返回size_t)比较时隐式转换出警告 - 翻转某行:用
std::reverse(matrix[i].begin(), matrix[i].end()),不是std::reverse(matrix[i].rbegin(), matrix[i].rend())—— 后者无效
for (size_t i = 0; i <h3>如果必须用 C 风格二维数组(如 int arr[N][M]),怎么安全取下标</h3><p>固定尺寸数组不能直接翻转行,得靠下标计算。关键在列循环的起止条件和步长:第 <code>i</code> 行若为奇数行,列下标应从 <code>M-1</code> 递减到 <code>0</code>;偶数行则从 <code>0</code> 递增到 <code>M-1</code>。别用 <code>for (int j = 0; j 然后靠 <code>arr[i][j * (i%2 ? -1 : 1)]</code> 这类写法——负下标会崩溃。</code></p>
- 正确写法是拆成两个分支:
if (i % 2 == 0)用正向for (int j = 0; j ,否则用反向 <code>for (int j = M-1; j >= 0; --j) - 注意
j >= 0中的0是int,而M若为size_t类型,M-1在M==0时会回绕成极大值,所以务必确保M > 0 - 访问元素统一用
arr[i][j],别试图用指针算偏移(如*(*(arr + i) + j)),易读性差且无收益
性能和边界细节:为什么不要在循环里反复调用 size()
matrix.size() 和 matrix[i].size() 在每次调用时都可能触发函数调用开销(虽然通常被内联),更严重的是:若遍历中意外修改了 matrix(比如 push_back 新行),后续 i 可能越界。实际项目中建议提前缓存:
- 外层数量:用
const size_t rows = matrix.size(); - 每行长度:若所有行等长(常见情况),用
const size_t cols = rows ? matrix[0].size() : 0;;否则每行单独缓存const size_t row_len = matrix[i].size(); - 蛇形逻辑本身无额外空间开销,时间复杂度稳定为
O(rows * cols),但用std::reverse会原地修改原数组——如果原始数据需保留,得先拷贝每行:std::vector<int> row_copy = matrix[i];</int>再翻转
真正容易被忽略的是:蛇形遍历默认按“行优先”折返,但有些需求要“列优先蛇形”(即第 0 列上→下,第 1 列下→上……),那整套下标逻辑就得重推——别想复用同一份代码。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











