Tips:大多数算法都有带_n的版本,这是简洁的指定输出range方法(指定起点和往后n个元素)。
解释:产生一个以某个数值开始的、间隔为1的数字序列
Defined in header <numeric> template< class ForwardIt, class T > void iota( ForwardIt first, ForwardIt last, T value );//11-20 template< class ForwardIt, class T > constexpr void iota( ForwardIt first, ForwardIt last, T value );//20+
例子:
std::list<int> l(10); std::iota(l.begin(), l.end(), -4);
其中-4为起点,填充的个数为10个。
二、一个或多个输入计算一个输出序列 transform解释:完成对一个或多个输入序列的整体运算。
template< class InputIt, class OutputIt, class UnaryOperation > OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op ); //<20 template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation > OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op );//<20
UnaryOperation一元运算,表示该操作仅需一个操作数完成。 BinaryOperation二元运算,表示该操作(函数)需要两个操作数才能完成;
例子:
std::vector<int> l(10); std::iota(l.begin(), l.end(), 2); std::vector<double> doublel(10); std::vector<double> ll(10); std::transform(l.begin(), l.end(), doublel.begin(), [](int ele) {return ele * 0.1; });//一元运算(一输入一输出) std::transform(l.begin(), l.end(), doublel.begin(),ll.begin(), [](int a,double b) {return a/b; });//二元运算(两输入一输出)
注意:std::transform不能保证unary_op和binary_op操作是按照序列顺序的。如果你想要按顺序改变序列的值,请使用for_each算法。
有时候需要计算两个容器之间的差值,使用std::transform就方便了:
std::vector<int> vec{1,2,3,4,15,6,7,8,9,10}; std::vector<int> vec2{2,3,4,5,6,7,8,9,10,11}; std::vector<int> result(10); std::transform(vec.begin(),vec.end(),vec2.begin(),result.begin(),[](int a,int b){return a-b;});三、序列自身运算 for_each
解释:和transform不同的是,for_each不创造新序列,结果可以通过引用参数直接放在原序列中,此外for_each保证会按照顺序完成计算。
std::vector<double> ivec(100); std::iota(ivec.begin(), ivec.end(), 1); for_each(ivec.begin(), ivec.end(), [](double i) {return i *= 2; });//参数是值类型,不会改变原序列 for_each(ivec.begin(), ivec.end(), [](double i) {std::cout << i << " "; }); std::cout << std::endl; for_each(ivec.begin(), ivec.end(), [](double &i) {return i *= 2; });//参数是引用类型,原序列可能改变 for_each(ivec.begin(), ivec.end(), [](double i) {std::cout << i << " "; });
C++17后支持带_n的版本。
四、序列差分操作 adjacent_difference解释:根据输入一个序列,输出一个差分序列。
Defined in header <numeric> template< class InputIt, class OutputIt > OutputIt adjacent_difference( InputIt first, InputIt last, OutputIt d_first );//(until C++20) template< class InputIt, class OutputIt > constexpr OutputIt adjacent_difference( InputIt first, InputIt last, OutputIt d_first );//(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first ); //(since C++17) template< class InputIt, class OutputIt, class BinaryOperation > OutputIt adjacent_difference( InputIt first, InputIt last, OutputIt d_first, BinaryOperation op );//(until C++20) template< class InputIt, class OutputIt, class BinaryOperation > constexpr OutputIt adjacent_difference( InputIt first, InputIt last, OutputIt d_first, BinaryOperation op );//(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation > ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first, BinaryOperation op );// (since C++17)
例子:
std::vector<double> ivec(100); std::iota(ivec.begin(), ivec.end(), 1); std::vector<double> diff_ivec; adjacent_difference(ivec.begin(), ivec.end(), std::back_inserter(diff_ivec)); for_each(diff_ivec.begin(), diff_ivec.end(), [](double i) {std::cout << i << " "; });
注意!!!An unmodified copy of *first is written to *d_first,也就是说第一个元素始终保持不变,长度不发生改变。
五、拷贝、条件拷贝、反向拷贝 copy copy_if copy_backward 5.1 copy and copy_ifDefined in header <algorithm> template< class InputIt, class OutputIt > OutputIt copy( InputIt first, InputIt last, OutputIt d_first );//(until C++20) template< class InputIt, class OutputIt > constexpr OutputIt copy( InputIt first, InputIt last, OutputIt d_first );//(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > ForwardIt2 copy( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first );//(since C++17) template< class InputIt, class OutputIt, class UnaryPredicate > OutputIt copy_if( InputIt first, InputIt last, OutputIt d_first, UnaryPredicate pred );//(since C++11)(until C++20) template< class InputIt, class OutputIt, class UnaryPredicate > constexpr OutputIt copy_if( InputIt first, InputIt last, OutputIt d_first, UnaryPredicate pred );//(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class UnaryPredicate > ForwardIt2 copy_if( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first, UnaryPredicate pred ); //(since C++17)
例子:
std::vector<double> ivec(100); std::iota(ivec.begin(), ivec.end(), 1); std::vector<double> copy_ivec; std::copy(ivec.begin(), ivec.end(), std::back_inserter(copy_ivec)); std::for_each(copy_ivec.begin(), copy_ivec.end(), [](double e) {std::cout << e << " "; }); std::cout << std::endl; std::vector<double> greaterThan50; std::copy_if(ivec.begin(), ivec.end(), std::back_inserter(greaterThan50), [](double ele) {return ele > 50; }); std::for_each(greaterThan50.begin(), greaterThan50.end(), [](double e) {std::cout << e << " "; }); std::cout << std::endl;
_n版本c++11就实现了支持。利用这个我们可以实现将int容器整体隐式转换成double。
5.2 反向填充式拷贝 copy_backward解释:将指定范围的元素粘贴到指定位置后。
template< class InputIt, class OutputIt, class UnaryPredicate > constexpr OutputIt copy_if( InputIt first, InputIt last, OutputIt d_first, UnaryPredicate pred ); template< class InputIt, class OutputIt > OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
例子:
std::vector<double> ivec(100); std::iota(ivec.begin(), ivec.end(), 1); std::vector<double> copy_ivec(130); std::copy_backward(ivec.begin(), ivec.end(), copy_ivec.end());5.3 倒序拷贝 reverse_copy
解释:反转原序列后拷贝进新的序列。
Defined in header <algorithm> template< class BidirIt, class OutputIt > OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first );//(until C++20) template< class BidirIt, class OutputIt > constexpr OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first );//(since C++20) template< class ExecutionPolicy, class BidirIt, class ForwardIt > ForwardIt reverse_copy( ExecutionPolicy&& policy, BidirIt first, BidirIt last, ForwardIt d_first );// (since C++17)
例子:
std::vector<double> ivec(100); std::iota(ivec.begin(), ivec.end(), 1); std::vector<double> copy_ivec; std::reverse_copy(ivec.begin(), ivec.end(), std::back_inserter(copy_ivec));六、填充重复值 fill fill_n
解释:用某个重复的数值来改写一个序列中的某一部分
template< class ForwardIt, class T > void fill( ForwardIt first, ForwardIt last, const T& value );//(until C++11) template< class OutputIt, class Size, class T > void fill_n( OutputIt first, Size count, const T& value );//(until C++11) template< class OutputIt, class Size, class T > OutputIt fill_n( OutputIt first, Size count, const T& value );//(since C++11,until C++20)
例子:
std::vector<double> t(1000); std::fill(t.begin(),t.end(),333);
_n版本的出现的时间是c++11。
七、产生规律序列 generate generate_n解释:产生一个规律的序列
template< class ForwardIt, class Generator > void generate( ForwardIt first, ForwardIt last, Generator g );//(until C++20) template< class ForwardIt, class Generator > constexpr void generate( ForwardIt first, ForwardIt last, Generator g );//(since C++20) template< class ExecutionPolicy, class ForwardIt, class Generator > void generate( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, Generator g );//(since C++17) template< class OutputIt, class Size, class Generator > void generate_n( OutputIt first, Size count, Generator g );//(until C++11) template< class OutputIt, class Size, class Generator > OutputIt generate_n( OutputIt first, Size count, Generator g );//(since C++11) (until C++20) template< class OutputIt, class Size, class Generator > constexpr OutputIt generate_n( OutputIt first, Size count, Generator g );//(since C++20) template< class ExecutionPolicy, class ForwardIt , class Size, class Generator > ForwardIt generate_n( ExecutionPolicy&& policy, ForwardIt first, Size count, Generator g );//(since C++17)
例子: 这个用来产生诸如0.004之类的序列相当好用,不过不带_n版本的需要在创建时指定大小。
std::vector<double> t; std::generate_n(std::back_inserter(t),1000,[n=0.0]()mutable {return (n++)*0.004;}); std::vector<double> t(1000); std::generate(t.begin(),t.end(),[n=0.0]()mutable{return (n++)*0.004;});
上述例子使用了C++14 才支持的lambda捕获初始化(C++11 则捕获变量之前要有定义),因为默认lambda不能修改捕获的变量,所以需要在小括号后加上mutable。
九、判等 equal解释:判断两个容器是否相等
Defined in header <algorithm> template< class InputIt1, class InputIt2 > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 );(until C++20) template< class InputIt1, class InputIt2 > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 );(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2 );(since C++17) template< class InputIt1, class InputIt2, class BinaryPredicate > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate p );(until C++20) template< class InputIt1, class InputIt2, class BinaryPredicate > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate p );(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPredicate > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, BinaryPredicate p ); (since C++17) template< class InputIt1, class InputIt2 > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 );(since C++14)(until C++20) template< class InputIt1, class InputIt2 > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 );(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2 ); (since C++17) template< class InputIt1, class InputIt2, class BinaryPredicate > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p );(since C++14)(until C++20) template< class InputIt1, class InputIt2, class BinaryPredicate > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p );(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPredicate > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p ); (since C++17)
例子:
std::vector<double> a{ 3,4,5 }; std::vector<double> b{ 2,3,4,5 }; std::cout << std::boolalpha << std::equal(a.begin(), a.end(), b.begin()) << std::endl; std::cout << std::boolalpha << std::equal(a.begin(), a.end(), a.begin()) << std::endl; std::cout << std::boolalpha << std::equal(a.begin(), a.end(), b.begin()+1,b.end()) << std::endl;十、累加 accumulate
解释:在某个初值基础上,累加指定范围的元素后返回这个和。
Defined in header <numeric> template< class InputIt, class T > T accumulate( InputIt first, InputIt last, T init );//(until C++20) template< class InputIt, class T > constexpr T accumulate( InputIt first, InputIt last, T init );//(since C++20) template< class InputIt, class T, class BinaryOperation > T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );//(until C++20) template< class InputIt, class T, class BinaryOperation > constexpr T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );//(since C++20)
例子:
std::vector<double> a{ 3,4,5 }; std::cout << std::accumulate(a.begin(), a.end(), 0.0) << std::endl;十一、内积 inner_product
解释:在某个初值基础上,返回两个向量的内积和。
template< class InputIt1, class InputIt2, class T > T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init );//(until C++20) template< class InputIt1, class InputIt2, class T > constexpr T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init );//(since C++20) template<class InputIt1, class InputIt2, class T, class BinaryOperation1, class BinaryOperation2> T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init, BinaryOperation1 op1, BinaryOperation2 op2 );//(until C++20) template<class InputIt1, class InputIt2, class T, class BinaryOperation1, class BinaryOperation2> constexpr T inner_product( InputIt1 first1, InputIt1 last1, InputIt2 first2, T init, BinaryOperation1 op1, BinaryOperation2 op2 );//(since C++20)
例子:
std::vector<double> b{ 2,3,4,5 }; std::vector<double> a{ 3,4,5,2 }; std::cout << std::inner_product(a.begin(), a.end(), b.begin(), 0.0);十二、原序列移除 remove remove_if
解释:在序列中移除指定数值或条件元素
template< class ForwardIt, class T > ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );//(until C++20) template< class ForwardIt, class T > constexpr ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );//(since C++20) template< class ExecutionPolicy, class ForwardIt, class T > ForwardIt remove( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, const T& value ); //(since C++17) template< class ForwardIt, class UnaryPredicate > ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p );//(until C++20) template< class ForwardIt, class UnaryPredicate > constexpr ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p );//(since C++20) template< class ExecutionPolicy, class ForwardIt, class UnaryPredicate > ForwardIt remove_if( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, UnaryPredicate p ); //(since C++17)
例子:
std::vector<double> vec{ 5,5,5,5,5,5,55,5,5,5,5,5 }; std::remove(vec.begin(), vec.end(), 55); std::vector<double> vec{ 2,4,4,5,8,3,2,5,5,5,5,5 }; std::remove_if(vec.begin(), vec.end(), [](double e) {return e < 3; });十三、移除至新序列 remove_copy remove_copy_if
解释:remove但是不影响原序列,结果存储到新的序列。
template< class InputIt, class OutputIt, class T > OutputIt remove_copy( InputIt first, InputIt last, OutputIt d_first, const T& value );//(until C++20) template< class InputIt, class OutputIt, class T > constexpr OutputIt remove_copy( InputIt first, InputIt last, OutputIt d_first, const T& value );//(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T > ForwardIt2 remove_copy( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first, const T& value ); //(since C++17) template< class InputIt, class OutputIt, class UnaryPredicate > OutputIt remove_copy_if( InputIt first, InputIt last, OutputIt d_first, UnaryPredicate p );//(until C++20) template< class InputIt, class OutputIt, class UnaryPredicate > constexpr OutputIt remove_copy_if( InputIt first, InputIt last, OutputIt d_first, UnaryPredicate p );//(since C++20) template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class UnaryPredicate > ForwardIt2 remove_copy_if( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first, UnaryPredicate p );// (since C++17)
例子:
std::remove_copy_if(vec.begin(), vec.end(), std::back_inserter(result), [](double e) {return e <= 3; }); std::remove_copy(vec.begin(), vec.end(), std::back_inserter(result), 2);十四、sort 排序
template< class RandomIt > void sort( RandomIt first, RandomIt last );//(until C++20) template< class RandomIt > constexpr void sort( RandomIt first, RandomIt last );//(since C++20) template< class ExecutionPolicy, class RandomIt > void sort( ExecutionPolicy&& policy, RandomIt first, RandomIt last );// (since C++17) template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp );//(until C++20) template< class RandomIt, class Compare > constexpr void sort( RandomIt first, RandomIt last, Compare comp );//(since C++20) template< class ExecutionPolicy, class RandomIt, class Compare > void sort( ExecutionPolicy&& policy, RandomIt first, RandomIt last, Compare comp );//(since C++17)
默认情况下,sort将会直接在原序列从小到大排列。如:
std::vector<double> dvec{2,3,2,5,61,23,5}; std::sort(dvec.begin(),dvec.end(),std::greater<double>());
其中谓词可以使用内置的函数对象,如上面说的从大到小。你要是喜欢用lambda也可以:
std::vector<double> dvec{2,3,2,5,61,23,5}; std::sort(dvec.begin(),dvec.end(),[](double l,double r){return l>r;});//lambda描述可以理解为排序后的序列应该元素满足的条件
比如序列3 4 2 1排序完成后,任取两个元素应该满足:
-
从小到大 l
关注打赏