C++标准库中的算法函数主要包括以下几类:
1不修改序列的操作
1.1 all_of any_of none_of 检查谓词是否对范围中所有、任一或无元素为true
all_of 所有元素满足某个条件
all_of函数用于判断一个区间内的所有元素是否都满足某个条件,如果是则返回true,否则返回false。
示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
// 判断是否所有元素都大于0
bool all_positive = std::all_of(v.begin(), v.end(), [](int i){ return i > 0; });
if(all_positive)
std::cout << "所有元素都大于0" << std::endl;
else
std::cout << "存在不大于0的元素" << std::endl;
// 判断是否所有元素都是偶数
bool all_even = std::all_of(v.begin(), v.end(), [](int i){ return i % 2 == 0; });
if(all_even)
std::cout << "所有元素都是偶数" << std::endl;
else
std::cout << "存在不是偶数的元素" << std::endl;
return 0;
}
存在不大于0的元素
存在不是偶数的元素
any_of 存在元素满足某个条件
any_of函数用于判断一个区间内是否存在至少一个元素满足某个条件,如果存在则返回true,否则返回false。
示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
// 判断是否存在大于3的元素
bool has_greater_than_3 = std::any_of(v.begin(), v.end(), [](int i){ return i > 3; });
if(has_greater_than_3)
std::cout << "存在大于3的元素" << std::endl;
else
std::cout << "所有元素都不大于3" << std::endl;
// 判断是否存在负数元素
bool has_negative = std::any_of(v.begin(), v.end(), [](int i){ return i < 0; });
if(has_negative)
std::cout << "存在负数元素" << std::endl;
else
std::cout << "所有元素都不是负数" << std::endl;
return 0;
}
存在大于3的元素
所有元素都不是负数
none_of 所有元素不满足某个条件
none_of函数用于判断一个区间内是否所有元素都不满足某个条件,如果是则返回true,否则返回false。
示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
// 判断是否所有元素都小于0
bool all_negative = std::none_of(v.begin(), v.end(), [](int i){ return i < 0; });
if(all_negative)
std::cout << "所有元素都不是负数" << std::endl;
else
std::cout << "存在负数元素" << std::endl;
// 判断是否所有元素都是偶数
bool all_even = std::none_of(v.begin(), v.end(), [](int i){ return i % 2 = 0; });
if(all_even)
std::cout << "所有元素都是偶数" << std::endl;
else
std::cout << "存在不是偶数的元素" << std::endl;
return 0;
}
所有元素都不是负数
存在不是偶数的元素
1.2 for_each 应用函数到范围中的元素
for_each函数用于对一个区间内的所有元素进行遍历,并执行指定的操作。它接受两个迭代器和一个函数对象作为参数,函数对象可以是函数指针、函数对象或者Lambda表达式。函数对象会被应用到区间内的每个元素上。
示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
void print(int i)
{
std::cout << i << " ";
}
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
// 使用函数指针
std::for_each(v.begin(), v.end(), print);
std::cout << std::endl;
// 使用Lambda表达式
std::for_each(v.begin(), v.end(), [](int i){ std::cout << i << " "; });
std::cout << std::endl;
// 使用函数对象
struct print_functor {
void operator()(int i) const {
std::cout << i << " ";
}
};
std::for_each(v.begin(), v.end(), print_functor());
std::cout << std::endl;
return 0;
}
1.3 for_each_n 应用一个函数对象到序列的前 n 个元素
1.4 count count_if 返回满足指定判别标准的元素数
count 计数
C++标准库中的count函数用于计算序列中等于指定值的元素个数
函数原型为:
template<class InputIt, class T>
typename iterator_traits<InputIt>::difference_type count(InputIt first, InputIt last, const T& value);
其中,first
和last
分别是表示序列起始位置和结束位置的迭代器,value
是需要计数的元素。函数返回一个整数,表示序列中等于value
的元素个数。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5};
int cnt = count(v.begin(), v.end(), 3);
cout << "Count of 3: " << cnt << endl;
return 0;
}
count_if 计数
count_if函数也接受两个迭代器表示的序列范围,但它接受一个谓词作为第三个参数。
它计算序列中使谓词返回true的元素的数量,并返回该数量。例如,下面是一个使用count_if函数计算vector中符合某个条件的元素数量的示例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {1, -2, 3, -4, 5};
int n = count_if(v.begin(), v.end(), [](int x){ return x < 0; }); // 计算负数的数量
cout << "There are " << n << " negative elements" << endl;
return 0;
}
在上述代码中,我们使用count_if函数计算了vector v中负数的数量。count_if函数根据谓词返回true的元素计数,我们直接输出结果即可。输出结果为:
There are 2 negative elements
简而言之,count函数用于计算某个元素值的数量,而count_if函数用于计算符合某个条件的元素的数量。它们的用法和参数有所不同,在使用时需要根据具体情况选择。
1.5 mismatch寻找两个范围出现不同的首个位置
1.6 find find_if find_if_not 寻找首个满足特定判别标准的元素
find 查找
C++标准库中的find函数用于在序列中查找指定元素,函数原型为:
template<class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value);
其中,first
和last
分别是表示序列起始位置和结束位置的迭代器,value
是需要查找的元素。函数返回一个迭代器,指向第一个等于value的元素。如果未找到,则返回last迭代器。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5};
auto it = find(v.begin(), v.end(), 3);
if (it != v.end()) {
cout << "Found " << *it << " at position " << distance(v.begin(), it) << endl;
} else {
cout << "Not found" << endl;
}
return 0;
}
find() 函数的底层实现,其实就是用==
运算符将 val 和 [first, last) 区域内的元素逐个进行比对。这也就意味着,[first, last) 区域内的元素必须支持==
运算符。
find_if 查找
find_if函数也接受两个迭代器表示的序列范围,但它接受一个谓词作为第三个参数。
它在序列中查找第一个使谓词返回true的元素,并返回一个迭代器指向该元素。如果序列中不存在符合条件的元素,则返回末尾迭代器。例如,下面是一个使用find_if函数查找vector中某个元素的示例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {1, -2, 3, -4, 5};
auto it = find_if(v.begin(), v.end(), [](int x){ return x < 0; }); // 查找第一个负数
if (it != v.end()) {
cout << "Negative element found at position " << distance(v.begin(), it) << endl;
} else {
cout << "No negative element found" << endl;
}
return 0;
}
在上述代码中,我们使用find_if函数查找了vector v中第一个负数的位置。如果序列中存在符合条件的元素,则返回指向该元素的迭代器,否则返回末尾迭代器。我们使用distance函数计算出该迭代器对应的位置,并输出结果。输出结果为:
Negative element found at position 1
简而言之,find函数用于查找某个元素值,而find_if函数用于查找符合某个条件的元素。它们的用法和参数有所不同,在使用时需要根据具体情况选择。
find_first_of
修改序列的操作
划分操作
排序操作
二分搜索操作(在已排序范围上)
其他已排序范围上的操作
集合操作(在已排序范围上)
堆操作
最小/最大操作
比较操作
排列操作
数值运算
未初始化内存上的操作
equal 判断序列是否相等
C++标准库中的equal函数用于判断两个序列是否相等。它接受两个迭代器表示的序列范围,以及一个可选的谓词,返回一个bool值表示两个序列是否相等。如果没有指定谓词,则默认使用相等运算符==
进行元素比较。
下面是一个使用equal函数的示例,比较两个vector是否相等:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {1, 2, 3, 4, 6};
if (equal(v1.begin(), v1.end(), v2.begin())) { // 判断v1和v2是否相等
cout << "v1 and v2 are equal" << endl;
} else {
cout << "v1 and v2 are not equal" << endl;
}
return 0;
}
在上述代码中,我们省略了谓词参数,equal函数默认使用相等运算符==
进行元素比较。
equal_range 查找序列中某个元素的范围
C++标准库中的equal_range函数用于查找序列中某个元素的范围。它接受两个迭代器表示的序列范围,以及一个待查找的元素值,返回一个pair对象,表示该元素在序列中出现的范围。pair对象的第一个元素是一个迭代器,指向序列中第一个等于该元素值的元素,第二个元素也是一个迭代器,指向序列中第一个大于该元素值的元素。
下面是一个使用equal_range函数的示例,查找vector中某个元素的范围:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {1, 2, 2, 3, 3, 3, 4, 5};
int x = 3;
auto range = equal_range(v.begin(), v.end(), x); // 查找元素x的范围
cout << "Element " << x << " occurs " << distance(range.first, range.second) << " times" << endl;
return 0;
}
在上述代码中,我们使用equal_range函数查找了vector v中元素值为3的范围。equal_range函数返回一个pair对象,表示该元素在序列中出现的范围。我们使用distance函数计算出该范围内元素的个数,并输出结果。输出结果为:
Element 3 occurs 3 times
在上述代码中,我们没有指定谓词参数,equal_range函数默认使用小于运算符(<)进行元素比较。如果我们希望使用其他比较方式,可以指定一个自定义的谓词。例如,下面的代码使用一个lambda表达式作为谓词,比较元素的绝对值是否相等:
auto range = equal_range(v.begin(), v.end(), x, [](int a, int b){ return abs(a) == abs(b); });
adjacent_find 查找第一组相邻的重复元素
adjacent_find() 函数用于查找第一组相邻的重复元素。它的语法如下:
template< class ForwardIt >
ForwardIt adjacent_find( ForwardIt first, ForwardIt last );
其中 first 和 last 分别是指向要搜索的元素范围的迭代器。如果找到相邻的重复元素,则返回一个指向第一个重复元素的迭代器。否则返回 last。
以下是 adjacent_find() 函数的使用示例:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
// 定义一个 vector 并初始化
std::vector<int> vec = {1, 2, 3, 3, 4, 5, 5, 6};
// 查找第一组相邻的重复元素
auto it = std::adjacent_find(vec.begin(), vec.end());
// 判断是否找到相邻的重复元素
if (it != vec.end()) {
std::cout << "Found adjacent duplicate elements at position " << std::distance(vec.begin(), it) << std::endl;
} else {
std::cout << "No adjacent duplicate elements found" << std::endl;
}
return 0;
}
Found adjacent duplicate elements at position 2
unique实现去重
可以使用 sort() 函数和 unique() 函数来实现去除容器中重复的元素的功能。它们的使用方法分别如下:
-
sort() 函数:对容器中的元素进行排序,使相同的元素相邻。
-
unique() 函数:从排好序的容器中移除相邻的重复元素。
以下是使用 sort() 和 unique() 函数实现去除容器中重复元素的示例:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
// 定义一个包含重复元素的 vector
std::vector<int> vec = {5, 3, 1, 2, 5, 4, 4, 3, 2};
// 对 vector 进行排序
std::sort(vec.begin(), vec.end());
// 使用 unique 函数去除相邻的重复元素
auto it = std::unique(vec.begin(), vec.end());
// 删除重复元素后调整 vector 大小
vec.resize(std::distance(vec.begin(), it));
// 输出去重后的 vector
for (auto i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
1 2 3 4 5
上面的示例中,我们首先定义了一个包含重复元素的 vector,然后对它进行排序,使相同的元素相邻。接着,我们使用 unique() 函数将相邻的重复元素移除,并返回一个指向新结尾的迭代器。最后,我们根据新结尾的迭代器调整 vector 的大小,以删除重复元素。
unique()
并非真正意义的erase
,而是将重复的元素放到容器的末尾,返回值是去重之后的尾地址。
真正实现去重:
std::vector<int> ModuleArr;
//排序
std::sort(ModuleArr.begin(), ModuleArr.end());
//去重
ModuleArr.erase(unique(ModuleArr.begin(), ModuleArr.end()), ModuleArr.end());
erase 删除元素
- 删除单个元素
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec = {1, 2, 3, 4, 5};
// 删除第三个元素
vec.erase(vec.begin() + 2);
// 输出剩余元素
for (int i : vec) {
std::cout << i << " ";
}
return 0;
}
1 2 4 5
- 删除一段范围内的元素
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec = {1, 2, 3, 4, 5};
// 删除第二个到第四个元素
vec.erase(vec.begin() + 1, vec.begin() + 4);
// 输出剩余元素
for (int i : vec) {
std::cout << i << " ";
}
return 0;
}
1 5
- 删除满足条件的元素
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec = {1, 2, 3, 4, 5};
// 删除偶数元素
vec.erase(std::remove_if(vec.begin(), vec.end(), [](int i) { return i %! 2 == 0; }), vec.end());
// 输出剩余元素
for (int i : vec) {
std::cout << i << " ";
}
return 0;
}
1 3 5
remove_copy_if
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> even_vec;
std::remove_copy_if(vec.begin(), vec.end(), std::back_inserter(even_vec),
[](int i) { return i % 2 = 0; });
std::cout << "原始容器中的元素:";
for (const auto& i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "新容器中的元素:";
for (const auto& i : even_vec) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
原始容器中的元素:1 2 3 4 5 6 7 8 9
新容器中的元素:2 4 6 8
在这个例子中,我们使用remove_copy_if函数将原容器中的偶数复制到一个新的容器中。我们使用了Lambda表达式作为谓词函数,筛选出原容器中的偶数元素。我们使用std::back_inserter函数将元素插入到新容器中,这样可以自动调整新容器的大小。最后,我们分别输出原始容器和新容器中的元素。
需要注意的是,remove_copy_if函数不会改变原始容器中的元素,而是将满足条件的元素复制到新的容器中。因此,原始容器中的元素和新容器中的元素是不一样的。
实现集合B-集合A
可以使用 remove_if() 函数结合 lambda 表达式来实现去除第二个序列中所有在第一个序列中出现的元素的功能。具体步骤如下:
- 将第一个序列中的元素保存到一个 std::set 中,用于判断第二个序列中的元素是否出现在第一个序列中。
- 使用 remove_if() 函数结合 lambda 表达式,将第二个序列中所有在第一个序列中出现的元素移除。
以下是代码示例:
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
int main() {
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = {2, 4, 6, 8, 10};
std::set<int> set1(vec1.begin(), vec1.end());
// 移除 vec2 中所有在 vec1 中出现的元素
vec2.erase(std::remove_if(vec2.begin(), vec2.end(), [&](int x) { return set1.count(x) > 0; }), vec2.end());
// 输出结果
std::cout << "vec1: ";
for (auto i : vec1) {
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "vec2: ";
for (auto i : vec2) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
vec1: 1 2 3 4 5
vec2: 6 8 10
上面的示例中,我们首先定义了两个 vector vec1 和 vec2,并将 vec1 中的元素保存到一个 std::set 中。然后,我们使用 remove_if() 函数结合 lambda 表达式,将 vec2 中所有在 vec1 中出现的元素移除。最后,我们输出处理后的 vec1 和 vec2。
replace
C++标准库中的replace函数可以将容器(或者数组)中的某个值替换为另一个值。这个函数定义在头文件中,其基本语法如下:
template<class ForwardIt, class T>
void replace(ForwardIt first, ForwardIt last, const T& old_value, const T& new_value);
其中,ForwardIt表示前向迭代器,first和last表示容器中的区间,old_value表示要替换的旧值,new_value表示新值。
下面是一个使用replace函数的例子,将vector容器中的某个值替换为另一个值:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vec = {1, 2, 3, 4, 5};
std::replace(vec.begin(), vec.end(), 3, 6);
std::cout << "替换后的vec容器:";
for (const auto& i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
替换后的vec容器:1 2 6 4 5
在这个例子中,我们使用了replace函数将vector容器中的3替换为6。通过指定容器的区间、旧值和新值,我们可以方便地进行替换操作。注意,replace函数会将所有等于旧值的元素全部替换为新值,而不是只替换第一个。如果容器中不存在旧值,则不会进行替换。
除了vector容器,replace函数也适用于其他容器和数组。例如,我们可以使用replace函数将数组中的某个值替换为另一个值:
#include <iostream>
#include <algorithm>
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
std::replace(arr, arr+5, 3, 6);
std::cout << "替换后的arr数组:";
for (const auto& i : arr) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
替换后的arr数组:1 2 6 4 5
reverse
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> vec{1, 2, 3, 4, 5};
// 反转整个向量
std::reverse(vec.begin(), vec.end());
// 输出反转后的向量
for (auto i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
// 反转部分向量
std::reverse(vec.begin() + 1, vec.end() - 1);
// 输出反转后的向量
for (auto i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
fill
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v(10); // 创建一个长度为10的vector
std::fill(v.begin(), v.end(), 5); // 将所有元素设置为5
for (auto i : v) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
generate
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> v(10); // 创建一个长度为10的vector
std::generate(v.begin(), v.end(), [](){ return rand() %100;}); // 随机生成每个元素的值
for (auto i : v) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
在该例子中,我们用了一个lambda表达式作为生成函数,它会生成一个0到99之间的随机数,用于填充vector。
查找连续子序列的search
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> haystack = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> needle = {4, 5, 6};
auto it = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end());
if (it != haystack.end()) {
std::cout << "Found at position " << it - haystack.begin() << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
return 0;
}
这个程序创建了两个向量,一个作为被搜索的序列,一个作为搜索的子序列,然后使用search函数在被搜索序列中查找子序列的位置,如果找到,则输出位置,否则输出“Not found”。注意,这个程序需要包含头文件和。
accumulate
inner_product
max_element
min_element
make_heap
sort_heap
push_heap
pop_heap
随机打乱序列的shuffle
参考文档:https://zh.cppreference.com/w/cpp/algorithm