本文最后更新于 34 天前,其中的信息可能已经有所发展或是发生改变。
一、核心概念回顾
遍历 = 按顺序访问容器中的每个元素
二、一维 vector 的遍历方法
方法1:下标遍历(最简单直观)
vector<int> v = {10, 20, 30, 40, 50};
// 1.1 传统for循环
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
// 输出:10 20 30 40 50
// 1.2 while循环
int i = 0;
while (i < v.size()) {
cout << v[i] << " ";
i++;
}
适用场景:需要知道元素索引位置时
方法2:迭代器遍历(标准库风格)
vector<int> v = {10, 20, 30, 40, 50};
// 2.1 传统迭代器
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
// 2.2 auto简化
for (auto it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
适用场景:需要兼容不同容器类型时
方法3:范围for循环(C++11,最简洁)
vector<int> v = {10, 20, 30, 40, 50};
// 3.1 只读遍历
for (int num : v) {
cout << num << " ";
}
// 3.2 修改元素
for (int& num : v) { // 用引用
num *= 2; // 每个元素乘以2
}
适用场景:只需要元素值,不需要索引时(最推荐)
方法4:反向遍历
vector<int> v = {10, 20, 30, 40, 50};
// 4.1 下标反向
for (int i = v.size() - 1; i >= 0; i--) {
cout << v[i] << " ";
}
// 输出:50 40 30 20 10
// 4.2 反向迭代器
for (auto rit = v.rbegin(); rit != v.rend(); rit++) {
cout << *rit << " ";
}
适用场景:需要从后往前处理
三、二维 vector 的遍历
方法1:双重循环(最常用)
vector<vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 1.1 双重下标
for (int i = 0; i < matrix.size(); i++) { // 遍历行
for (int j = 0; j < matrix[i].size(); j++) { // 遍历列
cout << matrix[i][j] << " ";
}
cout << endl;
}
// 1.2 范围for循环
for (const auto& row : matrix) { // 遍历每一行
for (int num : row) { // 遍历行中的每个元素
cout << num << " ";
}
cout << endl;
}
方法2:迭代器嵌套
vector<vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (auto row_it = matrix.begin(); row_it != matrix.end(); row_it++) {
for (auto col_it = row_it->begin(); col_it != row_it->end(); col_it++) {
cout << *col_it << " ";
}
cout << endl;
}
四、四种主要遍历方式的对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 下标访问 | 直观,容易理解 | 只能用于支持[]的容器 | 需要索引,简单遍历 |
| 迭代器 | 通用,所有容器都支持 | 语法稍复杂 | 通用代码,需要灵活性 |
| 范围for | 简洁,不易出错 | 不能获取索引 | 只需要元素值 |
| while循环 | 灵活,可控制复杂条件 | 手动控制迭代变量 | 条件复杂的情况 |
五、选择指南(初学者必看)
情况1:只需要读取值
// 推荐:范围for循环
for (int num : v) {
cout << num << " ";
}
// 最简单,不容易出错
情况2:需要修改值
// 推荐:带引用的范围for循环
for (int& num : v) {
num *= 2; // 修改元素
}
情况3:需要索引
// 推荐:传统for循环
for (int i = 0; i < v.size(); i++) {
cout << "索引" << i << ": " << v[i] << endl;
}
情况4:不确定遍历条件
// 推荐:while循环
auto it = v.begin();
while (it != v.end() && *it != 0) { // 遇到0就停止
cout << *it << " ";
it++;
}
六、代码模板(复制就能用)
模板1:基本遍历
vector<int> v = {1, 2, 3, 4, 5};
// 模板A:范围for循环(最常用)
for (int num : v) {
cout << num << " ";
}
// 模板B:带索引
for (int i = 0; i < v.size(); i++) {
cout << "v[" << i << "] = " << v[i] << endl;
}
模板2:二维遍历
vector<vector<int>> matrix = {
{1, 2, 3},
{4, 5, 6}
};
// 模板A:双重循环
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[i].size(); j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
// 模板B:范围for循环嵌套
for (const auto& row : matrix) {
for (int num : row) {
cout << num << " ";
}
cout << endl;
}
七、常见错误和注意事项
错误示例1:越界访问
vector<int> v = {1, 2, 3};
for (int i = 0; i <= v.size(); i++) { // ❌ 应该是 i < v.size()
cout << v[i] << " "; // 当i=3时会越界
}
错误示例2:遍历中修改容器大小
vector<int> v = {1, 2, 3, 4};
for (int i = 0; i < v.size(); i++) {
if (v[i] == 2) {
v.erase(v.begin() + i); // ❌ 删除元素会使迭代失效
}
}
正确做法:
vector<int> v = {1, 2, 3, 4};
for (auto it = v.begin(); it != v.end(); ) {
if (*it == 2) {
it = v.erase(it); // ✅ erase返回下一个迭代器
} else {
it++;
}
}
八、练习题目
练习1:统计元素
// 统计vector中大于10的元素个数
vector<int> nums = {5, 12, 3, 18, 7, 25};
int count = 0;
for (int num : nums) {
if (num > 10) {
count++;
}
}
cout << "大于10的元素个数:" << count << endl; // 输出:3
练习2:求和
// 求vector中所有元素的和
vector<int> nums = {1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
}
cout << "和为:" << sum << endl; // 输出:15
练习3:查找元素
// 查找特定元素
vector<int> nums = {10, 20, 30, 40, 50};
int target = 30;
bool found = false;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == target) {
cout << "找到" << target << ",索引为" << i << endl;
found = true;
break; // 找到就退出
}
}
if (!found) {
cout << "没找到" << target << endl;
}
九、总结表格
| 任务 | 推荐方法 | 示例 |
|---|---|---|
| 简单遍历 | 范围for | for (int num : v) |
| 需要索引 | 传统for | for (int i = 0; i < v.size(); i++) |
| 修改元素 | 引用for | for (int& num : v) |
| 复杂条件 | while | while (条件) |
| 反向遍历 | 反向迭代器 | for (auto rit = v.rbegin(); ...) |
| 二维遍历 | 嵌套范围for | for (const auto& row : matrix) |
十、一句话记住
基本原则:
- 只需要值 → 用范围for循环
- 需要索引 → 用传统for循环
- 条件复杂 → 用while循环
- 遍历二维 → 用嵌套循环
记住这句口诀:
“要值用范围,要位用下标,复杂用while,二维套着来”
多练习几次,这些方法就会成为你的自然反应!