修改序列式算法能对容器内容造成修改,而改变容器一般有两种方法:
(1)使用迭代器遍历序列的过程中,直接改变元素的值;
(2)在元素复制的过程中,改变元素的值。
能对容器内容造成改变的算法主要包括:复制、转换、互换、赋值、替换、逆转、排列等 8种。
1、复制
元素复制是指在两个容器变量之间进行元素传递。
(1)copy()
// 声明及定义
template <class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last)
{
*result = *first;
++result;
++first;
}
return result;
}
使用示例:
#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
using namespace std;
void print(int& ele)
{
cout << ele << ", ";
}
void main()
{
int arr[] = { 1,3,5,7,9,11,32,54,65 };
vector<int> v1;
v1.assign(arr, arr + 9);
cout << "vector v1: " << endl;
for_each(v1.begin(), v1.end(), print);
cout << endl;
list<int>l1(v1.size()),l2;
cout << l1.size() << " " << l2.size() << endl;
// copy(v1.begin(), v1.end(), back_inserter(l1));//参数 3 使用到了一个 插入迭代器
// or
copy(v1.begin(), v1.end(), l1.begin()); //使用这种形式就要预定存储空间
cout << "list l1: " << endl;
for_each(l1.begin(), l1.end(), print);
cout << endl;
}
(2)copy_backward()
//声明及定义
template <class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 copy_backward (BidirectionalIterator1 first,BidirectionalIterator1 last,BidirectionalIterator2 result);
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 copy_backward ( BidirectionalIterator1 first,BidirectionalIterator1 last,BidirectionalIterator2 result )
{
while (last!=first) //可以看到 copy_backward 是逆向遍历容器,而copy是正向遍历
*(--result) = *(--last);
return result;
}
用法示例:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int arr[] = { 10,20,30,40,50 };
vector<int> v(arr,arr+5); // 10 20 30 40 50
v.resize(v.size() + 3); // 重设容器大小 // 10 20 30 40 50 xx xx xx
// 从后往前 复制
copy_backward(v.begin(), v.begin()+5, v.end());// 10 20 30 10 20 30 40 50
for (int val : v)
cout << val << " ";
cout << endl;
return 0;
}
如果要把一个区间复制到前端,应使用copy(),目标位置应该是begin();
如果要把一个区间复制到后端,应使用copy_backward(),目标位置应该是end();
(3)copy_if() C++11
实现有条件的复制
//声明及定义
template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator copy_if (InputIterator first, InputIterator last,OutputIterator result,UnaryPredicate pred);
template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator copy_if (InputIterator first, InputIterator last,OutputIterator result,UnaryPredicate pred) // pred为真时 ,执行
{
while (first!=last)
{
if (pred(*first))
{
*result = *first;
++result;
}
++first;
}
return result;
}
用法示例:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool fun(int& elem) //判断是否大于等于 0
{
return !(elem < 0);
}
int main() {
vector<int> v1 = { 25,15,5,-5,-15, 0};
vector<int> v2(v1.size());
// auto it = copy_if(v1.begin(), v1.end(), v2.begin(), [](int i) {return !(i < 0); });
// OR
auto it = copy_if(v1.begin(), v1.end(), v2.begin(), fun);
v2.resize(distance(v2.begin(), it));
cout << "vector v2:";
for (int& val : v2)
cout << ' ' << val; // 结果: 25,15,5,0
cout << endl;
return 0;
}
(4)reverse_copy() C++11
逆转顺序并复制。
//声明及定义
template <class BidirectionalIterator, class OutputIterator>
OutputIterator reverse_copy (BidirectionalIterator first,BidirectionalIterator last, OutputIterator result);
template <class BidirectionalIterator, class OutputIterator>
OutputIterator reverse_copy (BidirectionalIterator first,BidirectionalIterator last, OutputIterator result)
{
while (first!=last)
{
--last;
*result = *last;
++result;
}
return result;
}
用法示例:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
vector<int> v;
v.resize(9); // allocate space // 要保证目标地址有足够空间,否则要使用insert迭代器
reverse_copy(arr, arr + 9, v.begin());
cout << "vector v:";
for (auto it = v.begin(); it != v.end(); ++it)
cout << *it<< ' ' ;
cout << endl;
return 0;
}
(5)copy_n()
template <class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n (InputIterator first, Size n, OutputIterator result);
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n (InputIterator first, Size n, OutputIterator result)
{
while ( n > 0 )
{
*result = *first;
++result;
++first;
--n;
}
return result;
}
用法示例:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int arr[] = { 10,20,30,40,50,60,70 };
vector<int> v;
copy_n(arr, 5, back_inserter(v));
cout << "vector v:";
for (auto it = v.begin(); it != v.end(); ++it)
cout << ' ' << *it; // vector v: 10 20 30 40 50
cout << endl;
return 0;
}