您当前的位置: 首页 >  容器

常见容器序列构造操作

发布时间:2021-05-22 11:10:56 ,浏览量:8

在这里插入图片描述 在这里插入图片描述 Tips:大多数算法都有带_n的版本,这是简洁的指定输出range方法(指定起点和往后n个元素)。

一、间隔1序列 iota

在这里插入图片描述

解释:产生一个以某个数值开始的、间隔为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_if
Defined 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
关注
打赏
1688896170
查看更多评论

暂无认证

  • 8浏览

    0关注

    105695博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.1707s