本文主要是介绍【C++提高编程-07】----C++ STL常用算法之遍历算法和算术生成算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
🎩 欢迎来到技术探索的奇幻世界👨💻
📜 个人主页:@一伦明悦-CSDN博客
✍🏻 作者简介: C++软件开发、Python机器学习爱好者
🗣️ 互动与支持:💬评论 👍🏻点赞 📂收藏 👀关注+
如果文章有所帮助,欢迎留下您宝贵的评论,
点赞加收藏支持我,点击关注,一起进步!
前言
STL(Standard Template Library)是C++标准库的一部分,提供了丰富的数据结构和算法,用于处理数据和实现常见的计算任务。STL中的算法分为几类,包括遍历算法、修改算法、排序算法、查找算法、数值算法等,每类算法都有其特定的应用场景和功能。
正文
01-遍历算法之for_each用法
for_each
是一种遍历算法,用于对指定范围内的每个元素执行特定操作。它的使用方式相对简单,但需要传入一个函数或函数对象作为操作的执行体。以下是关于for_each
的详细介绍和用法示例:
for_each
用法详解语法
template <class InputIterator, class Function> Function for_each(InputIterator first, InputIterator last, Function f);
InputIterator
:表示容器或范围的起始位置的迭代器。Function
:表示执行的操作,可以是函数或函数对象(仿函数)。参数
first
:表示要处理的范围的起始位置。last
:表示要处理的范围的结束位置,不包含在范围内。f
:表示要执行的操作,可以是函数或函数对象。功能
for_each
对[first, last)
范围内的每个元素执行f
操作。返回值
返回值类型为
Function
,通常是传入的函数或函数对象f
。示例
假设有一个整数数组
numbers
,我们想要将每个元素加倍并输出结果。可以这样使用for_each
:#include <iostream> #include <vector> #include <algorithm>void doubleAndPrint(int x) {std::cout << x * 2 << " "; }int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};// 使用 for_each 执行操作std::for_each(numbers.begin(), numbers.end(), doubleAndPrint);return 0; }
输出结果将是
2 4 6 8 10
,这里doubleAndPrint
函数就是传入for_each
的操作函数。在实际使用中,可以根据需要定义不同的操作函数或使用 lambda 表达式作为for_each
的操作体。注意事项
for_each
并不会改变容器中元素的值,它只是对每个元素执行操作。- 传入的操作函数或函数对象应符合对应的参数和返回值要求,以确保正确执行操作。
通过灵活运用
for_each
算法,可以简化遍历操作的代码,提高代码的可读性和维护性。
下面给出具体代码分析应用过程
这段代码展示了如何使用 for_each
算法进行遍历操作,分别使用普通函数和函数对象作为操作体。让我简要解释一下这部分代码:
-
头文件包含:
#include <algorithm> #include <vector>
这里包含了使用到的标准库头文件
<algorithm>
和<vector>
。 -
普通函数
print01
:void print01(int val) {cout << val << " "; }
print01
是一个普通函数,用于打印传入的整数val
。 -
函数对象
print02
:class print02 { public:void operator()(int val){cout << val << " ";} };
print02
是一个函数对象(也称为仿函数),重载了函数调用运算符operator()
,用于打印传入的整数val
。 -
test01
函数:void test01() {vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}// 使用 for_each 算法调用普通函数 print01for_each(v.begin(), v.end(), print01);cout << endl;// 使用 for_each 算法调用函数对象 print02for_each(v.begin(), v.end(), print02());cout << endl; }
- 在
test01
函数中,首先创建了一个vector<int>
容器v
,并将整数 0 到 9 添加到容器中。 - 然后使用
for_each
算法分别调用了print01
和print02
函数对象,对容器v
中的每个元素执行打印操作。
- 在
-
main
函数:int main() {test01();system("pause");return 0; }
main
函数调用了test01
函数,展示了for_each
算法的基本用法和不同操作体的应用。
总结:
- 这段代码演示了如何使用
for_each
算法对容器进行遍历操作,可以通过普通函数或函数对象来定义具体的操作。 - 函数对象的使用使得可以在一个地方定义多个不同的操作,增加了代码的灵活性和可复用性。
for_each
算法不会修改容器中的元素,只是对每个元素执行指定的操作,这符合算法的设计初衷。
通过这样的方式,可以简化遍历操作的代码实现,并使代码更加清晰和易于维护。
#include <algorithm>
#include <vector>
//普通函数
void print01(int val)
{cout << val << " ";
}
//函数对象
class print02
{
public:void operator()(int val){cout << val << " ";}
};
//for_each算法基本用法
void test01() {vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}//遍历算法for_each(v.begin(), v.end(), print01);cout << endl;for_each(v.begin(), v.end(), print02());cout << endl;
}
int main() {test01();system("pause");return 0;
}
02-遍历算法之transform用法
transform
是另一种常用的STL遍历算法,与for_each
不同的是,它不仅可以对容器中的每个元素执行操作,还可以将操作的结果存储到另一个容器或同一容器的不同位置。以下是关于transform
的详细介绍和用法示例:
transform
用法详解语法
template <class InputIterator, class OutputIterator, class UnaryOperation> OutputIterator transform(InputIterator first1, InputIterator last1,OutputIterator result, UnaryOperation op);
InputIterator
:表示容器或范围的起始位置的迭代器。OutputIterator
:表示结果存储位置的迭代器。UnaryOperation
:表示执行的操作,通常是一个函数对象(一元函数)。参数
first1
:表示要处理的范围的起始位置。last1
:表示要处理的范围的结束位置,不包含在范围内。result
:表示操作结果的存储位置,可以是另一个容器的begin()
迭代器或插入位置迭代器。op
:表示要执行的操作,通常是一个函数对象,接受一个参数并返回结果。功能
transform
对[first1, last1)
范围内的每个元素应用op
操作,并将结果存储到result
指定的位置。返回值
返回一个指向存储结果的迭代器
result + (last1 - first1)
。示例
假设有一个整数数组
numbers
,我们想要将每个元素加倍并存储到另一个数组doubled_numbers
中。可以这样使用transform
:#include <iostream> #include <vector> #include <algorithm>// 定义一个函数对象,用于将元素加倍 struct Double {int operator()(int x) const { return x * 2; } };int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};std::vector<int> doubled_numbers;// 使用 transform 执行操作std::transform(numbers.begin(), numbers.end(), std::back_inserter(doubled_numbers), Double());// 输出结果for (auto num : doubled_numbers) {std::cout << num << " ";}std::cout << std::endl;return 0; }
输出结果将是
2 4 6 8 10
,这里Double
是一个函数对象,作为transform
的操作体。在实际使用中,也可以使用 lambda 表达式或其他函数对象来定义操作体op
。注意事项
transform
可以将操作的结果存储到另一个容器(如示例中的doubled_numbers
),这对于在算法中生成新的数据集合非常有用。- 操作体
op
必须是一个一元函数,接受一个参数并返回操作后的结果。- 如果
result
容器的大小不足以容纳结果,则程序行为未定义;通常情况下应使用std::back_inserter
等函数来动态扩展容器大小。通过
transform
算法,可以将处理数据和存储结果有效地分离,提高了代码的模块化和可维护性,是处理数据转换和映射的常用工具之一。
下面给出代码分析应用过程:
这段代码演示了如何使用 transform
算法来对一个容器中的元素进行转换,并将结果存储到另一个容器中。让我来简要解释一下:
-
头文件包含:
#include <vector> #include <algorithm>
这里包含了使用到的标准库头文件
<vector>
和<algorithm>
。 -
函数对象
TransForm
:class TransForm { public:int operator()(int val){return val;} };
TransForm
是一个函数对象(仿函数),重载了函数调用运算符operator()
,用于对传入的整数val
进行转换操作。在这个例子中,它实际上是一个恒等函数,返回原始的输入值。 -
函数对象
MyPrint
:class MyPrint { public:void operator()(int val){cout << val << " ";} };
MyPrint
是另一个函数对象,用于打印传入的整数val
。 -
test01
函数:void test01() {vector<int> v;for (int i = 0; i < 10; i++){v.push_back(i);}vector<int> vTarget; // 目标容器vTarget.resize(v.size()); // 目标容器需要提前开辟空间// 使用 transform 算法对容器 v 中的每个元素应用 TransForm,并将结果存储到 vTarget 中transform(v.begin(), v.end(), vTarget.begin(), TransForm());// 使用 for_each 算法打印 vTarget 中的每个元素for_each(vTarget.begin(), vTarget.end(), MyPrint()); }
- 在
test01
函数中,首先创建了一个vector<int>
容器v
,并向其中插入整数 0 到 9。 - 创建了另一个
vector<int>
容器vTarget
作为目标容器,并调整其大小以匹配v
的大小。 - 使用
transform
算法对容器v
中的每个元素应用TransForm
函数对象,并将结果存储到vTarget
中。 - 最后,使用
for_each
算法和MyPrint
函数对象打印vTarget
中的每个元素。
- 在
-
main
函数:int main() {test01();system("pause");return 0; }
main
函数调用了test01
函数,展示了transform
算法的基本用法和将操作结果存储到另一个容器的实际应用。
总结:
transform
算法能够对一个容器中的元素进行操作,并将结果存储到另一个容器或同一容器的不同位置,比如示例中的vTarget
。- 使用函数对象(如
TransForm
和MyPrint
)可以灵活定义操作,增强代码的可复用性和可维护性。 - 需要注意的是,目标容器在使用
transform
算法之前需要预先分配足够的空间,以确保存储结果的正确性。
通过这样的方式,可以有效地进行数据转换和处理,使代码更加清晰和模块化。
#include<vector>
#include<algorithm>
//常用遍历算法 搬运 transform
class TransForm
{
public:int operator()(int val){return val;}
};
class MyPrint
{
public:void operator()(int val){cout << val << " ";}
};
void test01()
{vector<int>v;for (int i = 0; i < 10; i++){v.push_back(i);}vector<int>vTarget; //目标容器vTarget.resize(v.size()); // 目标容器需要提前开辟空间transform(v.begin(), v.end(), vTarget.begin(), TransForm());for_each(vTarget.begin(), vTarget.end(), MyPrint());
}
int main() {test01();system("pause");return 0;
}
03-算术生成算法之accumulate用法
accumulate
是另一个常用的STL算法,用于计算序列中元素的累加值。以下是关于accumulate
的详细介绍和用法示例:
accumulate
用法详解语法
template <class InputIterator, class T> T accumulate(InputIterator first, InputIterator last, T init);
InputIterator
:表示容器或范围的起始位置的迭代器。T
:表示累加结果的类型,通常是元素类型的累加结果类型。init
:表示初始值,累加的起始点。参数
first
:表示要累加的范围的起始位置。last
:表示要累加的范围的结束位置,不包含在范围内。init
:表示累加的初始值,累加从这个值开始。功能
accumulate
对[first, last)
范围内的元素进行累加,初始值为init
,并返回累加的结果。返回值
返回累加后的结果,类型为
T
。示例
假设有一个整数数组
numbers
,我们想要计算数组中所有元素的累加和。可以这样使用accumulate
:#include <iostream> #include <vector> #include <numeric> // 包含 accumulate 函数int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};// 使用 accumulate 计算累加和int sum = std::accumulate(numbers.begin(), numbers.end(), 0);std::cout << "Sum of elements: " << sum << std::endl;return 0; }
输出结果将是
Sum of elements: 15
。在这个例子中,accumulate
函数将整数数组numbers
中的所有元素累加起来,初始值为0
。注意事项
accumulate
可以用于各种数据类型,不限于整数。- 初始值
init
的类型必须与累加结果的类型相容,通常为整数或浮点数。- 如果范围
[first, last)
是空的,accumulate
将直接返回初始值init
。通过
accumulate
算法,可以方便地计算序列中元素的累加和,是处理累加操作的常用工具之一。
下面给出具体代码分析应用过程:
这段代码展示了如何使用 accumulate
算法来计算整数向量中所有元素的累加和。让我来简要解释一下:
-
头文件包含:
#include <numeric> #include <vector>
这里包含了使用到的标准库头文件
<numeric>
和<vector>
。 -
test01
函数:void test01() {vector<int> v;for (int i = 0; i <= 100; i++) {v.push_back(i);}int total = accumulate(v.begin(), v.end(), 0);cout << "total = " << total << endl; }
- 在
test01
函数中,首先创建了一个vector<int>
容器v
,并使用循环将整数 0 到 100 插入到向量中。 - 调用
accumulate
算法计算了容器v
中所有元素的累加和。参数解释如下:v.begin()
和v.end()
表示累加的范围是从容器v
的开头到末尾(不包括末尾)。0
是累加的初始值,即从0开始累加。
- 将计算得到的总和
total
输出到标准输出流cout
中。
- 在
-
main
函数:int main() {test01();system("pause");return 0; }
main
函数调用了test01
函数,展示了accumulate
算法的使用方式和计算结果的输出。
总结:
accumulate
算法能够方便地对容器中的元素进行累加操作,从而计算它们的总和。- 初始值
0
确保了即使容器为空,也能正确返回初始值作为累加结果。 - 使用
accumulate
算法可以避免显式使用循环来计算累加和,简化了代码并提高了可读性。
通过这样的方式,可以快速、有效地处理需要累加操作的情况,适用于各种数据类型和复杂度的累加需求。
#include <numeric>
#include <vector>
void test01()
{vector<int> v;for (int i = 0; i <= 100; i++) {v.push_back(i);}int total = accumulate(v.begin(), v.end(), 0);cout << "total = " << total << endl;
}
int main() {test01();system("pause");return 0;
}
04-算术生成算法之fill用法
fill
是STL中的一个算法,用于将指定范围内的所有元素设置为给定的值。以下是关于fill
的详细介绍和用法示例:
fill
用法详解语法
template <class ForwardIterator, class T> void fill (ForwardIterator first, ForwardIterator last, const T& value);
ForwardIterator
:表示容器或范围的起始位置的迭代器类型。T
:表示要填充的值的类型。first
:表示要填充的范围的起始位置。last
:表示要填充的范围的结束位置,不包含在范围内。value
:表示要填充到范围中的值。参数
first
:要填充的范围的起始位置。last
:要填充的范围的结束位置,不包含在范围内。value
:要填充到范围中的值。功能
fill
算法用指定的值value
填充[first, last)
范围内的所有元素。返回值
无。
示例
假设有一个整数数组
numbers
,我们想要将数组中的所有元素设置为0
。可以这样使用fill
:#include <iostream> #include <vector> #include <algorithm> // 包含 fill 函数int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};// 使用 fill 将数组中所有元素设置为 0std::fill(numbers.begin(), numbers.end(), 0);// 打印填充后的结果for (int num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0; }
输出结果将是
0 0 0 0 0
。在这个例子中,fill
函数将整数数组numbers
中的所有元素都设置为0
。注意事项
fill
可以用于各种数据类型,不限于整数。- 使用
fill
算法可以有效地初始化或重置容器中的元素。fill
不检查last
迭代器是否在范围内,使用时应保证范围有效。通过
fill
算法,可以方便地将容器中的元素设置为指定值,是处理填充操作的常用工具之一。
下面给出具体代码分析应用过程:
这段代码演示了如何使用 fill
算法来填充整数向量中的所有元素为指定的值。让我来简要解释一下:
-
头文件包含:
#include <numeric> #include <vector> #include <algorithm> #include <iostream>
这里包含了使用到的标准库头文件
<numeric>
,<vector>
,<algorithm>
和<iostream>
。 -
自定义函数对象
myPrint
:class myPrint { public:void operator()(int val) {std::cout << val << " ";} };
myPrint
是一个重载了函数调用运算符()
的类,用于在for_each
算法中打印每个元素的值。 -
test01
函数:void test01() {std::vector<int> v;v.resize(10); // 调整向量大小为10个元素// 使用 fill 算法将向量 v 中的所有元素设置为 100std::fill(v.begin(), v.end(), 100);// 使用 for_each 算法和自定义的 myPrint 函数对象打印向量中的每个元素std::for_each(v.begin(), v.end(), myPrint());std::cout << std::endl; }
- 在
test01
函数中,首先创建了一个大小为 10 的整数向量v
。 - 使用
fill
算法将向量v
中的所有元素设置为100
。v.begin()
表示填充的起始位置,v.end()
表示填充的结束位置(不包含在范围内)。 - 使用
for_each
算法和自定义的myPrint
函数对象,遍历打印向量v
中的每个元素值。
- 在
-
main
函数:int main() {test01();system("pause");return 0; }
main
函数调用了test01
函数,展示了fill
算法的使用方式和填充后的输出结果。
总结:
fill
算法通过指定的值将容器中的指定范围内的所有元素进行填充。- 在本例中,
fill
将整数向量v
中的所有元素设置为100
。 - 使用函数对象
myPrint
可以在遍历过程中自定义操作,这里用于打印每个元素。 fill
是初始化或重置容器元素的有效工具,能够简化代码并提高可读性。
通过这样的方式,可以快速、方便地对容器中的元素进行填充操作,适用于各种数据类型和填充需求。
#include <numeric>
#include <vector>
#include <algorithm>
class myPrint
{
public:void operator()(int val){cout << val << " ";}
};
void test01()
{vector<int> v;v.resize(10);//填充fill(v.begin(), v.end(), 100);for_each(v.begin(), v.end(), myPrint());cout << endl;
}
int main() {test01();system("pause");return 0;
}
总结
- 遍历算法帮助在容器内迭代元素并执行操作,如输出、转换或计算。
- 算术生成算法用于填充或生成容器的元素,常用于初始化和重置操作。
- 这些算法能够显著减少代码量并提高可读性,是C++中处理数据和容器操作的强大工具。
这篇关于【C++提高编程-07】----C++ STL常用算法之遍历算法和算术生成算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!