【C++ STL】遍历算法

0 阅读3分钟

遍历算法

遍历算法的核心目的:按规则访问容器中的每个 / 部分元素,并执行指定操作; 核心头文件:#include <algorithm> 迭代器区间:统一遵循「左闭右开」原则([first, last)),即包含 first,不包含 last

for_each最常用的遍历算法

  • 函数原型:for_each(开始迭代器,结束迭代器,一元可调用对象(函数指针/Lambda/仿函数,参数为单个元素));返回值为传入的可调用对象。
  • 功能:遍历[first, last) 区间内的每一个元素,对每个元素执行自定义操作(无返回值,仅执行「动作」),是 STL 最基础、最灵活的遍历算法。

函数使用

  • 普通函数作为操作
#include <vector>
#include <algorithm>
// 普通函数
void printInt(int val)
{
	cout << val << " ";
}

int main()
{
	vector<int> v = { 5, 10, 15, 20, 25 };

	// 普通函数,打印遍历出来的元素
	for_each(v.begin(), v.end(), printInt);
	// 输出结果5 10 15 20 25

	return EXIT_SUCCESS;
};

如果在遍历时需要修改元素,则可以传入元素的引用:

// 普通函数
void printInt(int val)
{
	cout << val << " ";
}

// 普通函数,参数为引用类型
void addTen(int& val)
{
	val += 10;
}

int main()
{
	vector<int> v = { 5, 10, 15, 20, 25 };

	// 遍历并修改元素
	for_each(v.begin(), v.end(), addTen);

	// 普通函数,打印遍历出来的元素
	for_each(v.begin(), v.end(), printInt);
	// 输出结果15 20 25 30 35

	return EXIT_SUCCESS;
};
  • 仿函数作为操作
// 仿函数
struct PrintInt {
	// 重载()运算符
	void operator()(int val) const
	{
		cout << val << " " << endl;
	}
};

int main()
{
	vector<int> v = { 5, 10, 15, 20, 25 };

	// 仿函数,打印遍历出来的元素
	for_each(v.begin(), v.end(), PrintInt());
	// 输出结果5 10 15 20 25

	return EXIT_SUCCESS;
};
  • lambda表达式作为操作
int main()
{
	vector<int> v = { 5, 10, 15, 20, 25 };

	// lambda表达式,遍历并修改元素
	for_each(v.begin(), v.end(), [](int& val) {
		val *= 2;
		});

	// lambda表达式,打印遍历出来的元素
	for_each(v.begin(), v.end(), [](int val) {
		cout << val << " ";
		});
	// 输出结果10 20 30 40 50
	cout << endl;

	return EXIT_SUCCESS;
};

注意点

修改元素必须用引用:Lambda / 函数参数需写 int&(而非 int),否则仅操作元素副本,原容器无变化; 自定义类型用 const&:遍历自定义类型时,参数用 const Person& 避免不必要的拷贝,提升效率; 不支持提前终止:for_each 会强制遍历完整个区间,无法像普通 for 循环那样用 break 退出; 并行遍历:C++17 后可加执行策略(如 std::execution::par)实现多线程并行遍历,适合大数据量场景。

进阶遍历算法

for_each_n(c++ 17新增)

仅遍历区间的前 n 个元素(解决 for_each 必须遍历全部的问题)。

vector<int> v = { 5, 10, 15, 20, 25 };

// 仅遍历前3个元素
for_each_n(v.begin(), 3, [](int val) {
	cout << val << " ";
	});
// 输出结果5 10 15
cout << endl;

transform(遍历 + 变换)

遍历原区间,对每个元素执行变换操作,并将结果存入新区间(或原区间),是「遍历 + 输出」的组合算法。

核心区别 vs for_each

  • for_each:侧重「执行操作」(如打印、修改原元素),无返回值;
  • transform:侧重「生成新值」(如元素 ×2 后存入新容器),必须指定输出迭代器。
vector<int> v = { 5, 10, 15, 20, 25 };
vector<int> v1(v.size());

transform(v.begin(), v.end(), v1.begin(), [](int val) {
	return val * 2;
	});

for_each(v1.begin(), v1.end(), [](int val) {cout << val << ","; });
// 输出结果10,20,30,40,50

return EXIT_SUCCESS;

遍历+条件判断

遍历区间,判断元素是否满足指定条件(返回 bool),属于「遍历 + 判断」的简化算法。 all_of所有元素都满足条件 → true any_of至少一个元素满足条件 → true none_of没有元素满足条件 → true

vector<int> v = { 5, 10, 15, 20, 25 };
	
// 所有元素都大于5,输出结果0
bool ret = all_of(v.begin(), v.end(), [](int val) {return val > 5; });
cout << ret << endl;

// 至少一个元素大于5,输出结果1
ret = any_of(v.begin(), v.end(), [](int val) {return val > 5; });
cout << ret << endl;

// 没有1个元素大于5,输出结果0
ret = none_of(v.begin(), v.end(), [](int val) {return val > 5; });
cout << ret << endl;