本节所介绍的几个算法,是在一个区间内移除某些元素。这些算法并不能改变元素的数量,它们只是以逻辑上的思考,将原本置于后面的“不移除元素”向前移动,覆盖那些被移除的元素而已。它们都返回新区间的逻辑终点。(也就是最后一个“不移除元素”的下一位置)
1. 移除某些特定元素
下面以程序示范remove()和remove_if()的用法,后面再加以说明:
/*
ForwardIterator remove(ForwardIterator beg, ForwardIterator end, const T& value)
ForwardIterator remove_if(ForwardIterator beg, ForwardIterator end, UnaryPredicate op)
*/
#include<iostream>
#include<vector>
#include<algorithm>
#include <iterator>
#include <functional>
using namespace std;
int main()
{
vector<int> coll;
for(int i = 2; i <= 6; ++i)
{
coll.push_back(i);
}
for(int i = 4; i <= 9; ++i)
{
coll.push_back(i);
}
for(int i = 1; i <= 7; ++i)
{
coll.push_back(i);
}
cout << "coll: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
vector<int>::iterator pos;
pos = remove(coll.begin(), coll.end(), 5);
cout << "size not changed: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
coll.erase(pos, coll.end());
cout << "size changed: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
//移除比 4小的元素
coll.erase(remove_if(coll.begin(), coll.end(), bind2nd(less<int>(), 4)), coll.end());
cout << "<4 removed: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
输出结果如下:
由上述结果可以看出,第一次调用remove移除值为5的元素后,容器的大小并没有改变,只是元素依次向前覆盖了值为5的元素。而由erase后的结果可以看出最后的5,6,7被删除了,说明一开始的pos指向了最后一个5的位置处。
所以,我们在使用remove这个算法的时候一定要清楚它的实现原理,不然可能就会误以为它直接把要移除的元素给去掉了,直接达到第三步的结果,而事实上并非如此!
还有两个类似的函数,复制时一并移除元素remove_copy和remove_copy_if,在这里就不多说了。
OutputIterator remove_copy(InputIterator sourceBeg, InputIterator sourceBeg, OutputIterator destBeg, const T& value)
OutputIterator remove_copy_if(InputIterator sourceBeg, InputIterator sourceBeg, OutputIterator destBeg, UnaryPredicate op)
2. 移除重复元素
移除连续重复元素
ForwardIterator unique(ForwardIterator beg, ForwardIterator end)
ForwardIterator remove(ForwardIterator beg, ForwardIterator end, BinaryPredicate op)
- 以上两种形式都会移除连续重读元素中的多余元素。
第一形式将区间[beg,end)内所有“与前一元素相等”的元素移除。所以,原序列必须先经过排序,才能使用这个算法移除所有重复元素。
同上面的remove算法一样,该算法也有另外两种形式,这里也只给出其函数的声明。
OutputIterator unique_copy(InputIterator sourceBeg, InputIterator sourceBeg, OutputIterator destBeg)
OutputIterator remove_copy_if(InputIterator sourceBeg, InputIterator sourceBeg, OutputIterator destBeg, BinaryPredicate op)