C++算法库
文章目录
算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。
》》概念约束
C++20 在命名空间 std::ranges 中提供大多数算法的受约束版本,在这些算法中,范围既可以由迭代器-哨位对,也可以由单个 range 实参指定,还支持投影和成员指针可调用对象。
cpp
std::vector<int> v {7, 1, 4, 0, -1};
std::ranges::sort(v); // 受约束算法
- 头文件
cpp
#include <algorithm>
#include <numeric>
#include <memory>
#include <ranges> //C++20
复制操作
copy , copy_if
- copy 复制范围
[first, last)
中的元素到从d_first
开始的另一范围(复制目标范围) - copy_if 对对所要求的元素则返回 true 的一元谓词执行copy
first, last ---要复制的元素范围
d_first --- 目标范围的起始
cpp
vector<int> a = {1,2,3,4,5};
vector<int> b(10);
std::copy(a.begin() , a.end() , b.begin());
for(auto x : b)std::cout << x << " "; //1 2 3 4 5 0 0 0 0 0
//std::back_inserter用于动态获取b.end()位置插入
std::copy_if(a.begin() , a.end() , std::back_inserter(b), [](int x){return x % 2 == 0;});
for(auto x : b)std::cout << x << " ";//1 2 3 4 5 0 0 0 0 0 2 4
- ranges
cpp
std::ranges::copy(a , b.begin());
std::ranges::copy_if(a , b.begin(), [](int x){return x % 2 == 0;});
copy_n
复制始于 first
的范围中恰好 count
个值到始于 result
的范围。
first --- 复制来源的元素范围起始
count --- 要复制的元素数
result --- 目标范围起始
cpp
std::string in {"1234567890"};
std::string out;
std::copy_n(in.begin(), 4, std::back_inserter(out));//1234
std::cout << out << '\n';
- ranges
cpp
std::ranges::copy_n(in.begin(), 4, std::back_inserter(out));//1234
copy_backward
(按从后往前的顺序复制一个范围内的元素)
将范围 [first, last)
内的元素复制到终于 d_last
的范围。以逆序复制元素(首先复制末元素),但保持相对顺序。
first, last --- 要复制的元素范围
d_last --- 目标范围的结尾
cpp
std::vector<int> source = {1,2,3,4,5};
std::vector<int> destination(6);
std::copy_backward(source.begin(), source.end(), destination.end());
for(auto x : destination)std::cout << x << " ";//0 1 2 3 4 5
- ranges
cpp
std::ranges::copy_backward(source, destination.end());
交换操作
swap
交换两个对象的值
cpp
vector<int> a = {1,2,3,4,5};
vector<int> b = {5,4,3,2,1};
std::swap(a, b);
for(auto x : a)cout << x << " ";//5 4 3 2 1
for(auto x : b)cout << x << " ";//1 2 3 4 5
swap_ranges
交换两个范围的元素
在范围 [first1, last1)
和始于 first2
的另一范围间交换元素。
first1, last1 --- 要交换的第一个元素范围
first2 --- 要交换的第二个元素范围的起始
cpp
std::vector<char> v{'a', 'b', 'c', 'd', 'e'};
std::list<char> l{'1', '2', '3', '4', '5'};
std::swap_ranges(v.begin(), v.begin() + 3, l.begin());
for(auto x : l)cout << x << " "; //a b c 4 5
- ranges
在第一范围 [first1, first1 + M)
与第二范围 [first2, first2 + M)
交换
cpp
std::vector<char> v{'a', 'b', 'c', 'd', 'e' , 'f' ,'g' , 'h'};
std::ranges::swap_ranges(v.begin(), v.begin() + 2, v.begin() + 4 , v.begin() + 6);
for(auto x : v)cout << x << " "; //e f c d a b g h
iter_swap
交换两个迭代器所指向的元素
cpp
vector<int> a = {1,2,3,4,5};
vector<int> b = {5,4,3,2,1};
std::iter_swap(a.begin() , b.begin());
std::cout << a[0] << " " << b[0] << std::endl;//5 1
变换操作
transform
将一个函数应用于某一范围的各个元素,并在目标范围存储结果
应用一元函数 unary_op
到 [first1, last1)
所定义的范围
应用二元函数 binary_op
到来自两个范围的元素对:一个以 [first1, last1)
定义,而另一个始于 first2
cpp
std::string s{"hello"};
std::transform(s.begin(), s.end(),
s.begin(), // 写入相同位置
[](unsigned char c) { return std::toupper(c); });
std::cout << s << '\n'; //HELLO
vector<int> ordinals = {1,2,3,4,5};
std::transform(ordinals.cbegin(), ordinals.cend(), ordinals.cbegin(),
ordinals.begin(), [](int a , int b){return a + b;});
for(auto x : ordinals)cout << x << " ";//2 4 6 8 10
- ranges
cpp
std::ranges::transform(s,s.begin(), // 写入相同位置
[](unsigned char c) { return std::toupper(c); });
std::ranges::transform(ordinals , ordinals, ordinals.begin(), [](int a , int b){return a + b;});
replace
将所有满足特定判别标准的值替换为另一个值
以 new_value
替换范围 [first, last)
中所有满足特定判别标准的元素。
cpp
vector<int> a = {1,2,3,2,5};
//所有为2的值替换为88
std::replace(a.begin(), a.end(), 2, 88);
for(auto x : a)cout << x << " ";// 1 88 3 88 5
- ranges
cpp
std::ranges::replace(a, 2, 88);
replace_copy replace_copy_if
复制一个范围,并将满足特定判别标准的元素替换为另一个值
复制来自范围 [first, last)
的元素到始于 d_first
的范围,复制过程中以 new_value
替换所有满足特定判别标准的元素。
cpp
std::vector<int> v{1,1,1,2,3,4};
std::replace_copy(v.begin(), v.end(),v.begin(),1, 99);
for(auto x : v)cout << x << " ";//99 99 99 2 3 4
cpp
std::vector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
std::replace_copy_if(v.begin(), v.end(),
v.begin(),//输出到原地开头
[](int n){ return n > 5; }, 99);
for(auto x : v)cout << x << " ";
- ranges
cpp
std::ranges::replace_copy(v,v.begin(),1, 99);
std::ranges::replace_copy_if(v,v.begin(),[](int n){ return n > 5; }, 99);