remove(beg,end,value)和remove_if(beg,end,op)
1:迭代器类型:前向迭代器
2:返回值类型:前向迭代器
3:算法功能:无op版本,移除区间[beg,end),有op版本,移除满足op(elem)的元素
4:复杂度:线性复杂度
5:这个算法的特殊在于,它并不是真的删除了元素,而是遇到要删除的元素时让后继元素去覆盖它
6:list提供了属于它自身的成员函数remove,由于该算法会变动元素,所以不能作用与关联容器上,应使用其自身成员函数erase()
int main()
{
vector<int>coll = {1,2,3,4,5};
remove(coll.begin(), coll.end(),3);
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout," "));//12455
}
当我们删除元素5而不是3时候我们会惊讶的发现,算法毫不起作用
那我们应该如何正确使用这个算法去删除我们想要删除的元素呢?
因为remove返回一个指向新的终点(指向删除后序列的逾尾)的迭代器,所以我们可以利用这个迭代器完成我们的目标。
int main()
{
vector<int>coll = {1,2,3,3,4,5,6,9};
auto e=remove(coll.begin(), coll.end(),3);
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout," "));//12456969
cout << endl;
coll.erase(e,coll.end());//删除指定区间的元素
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));//124569
}
distance(iterator,iterator2)返回两个迭代器之间的距离
更易型算法与关联式容器
如果我们将remove()的泛化版本作用如关联式容器,会出现问题-----破坏其已序的特性。这使我们无法在关联式容器身上运用移除性算法,那我们如何从关联容器中删除元素呢?很简单,因为关联容器自身定义了自己的删除函数。
int main()
{
set<int>coll = {1,2,3,4,3,5}; //124535
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout," "));//12345
cout << endl;
coll.erase(3);
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));//1245
}
由这个例子我们可以知道,就算一个泛型算法各方面都满足要求但容器自身成员函数有该算法的特例化时候,我们都应该调用成员函数,因为这个算法是为该容器量身定制的,效率更高,更安全。
remove_if的使用例子
int main()
{
//如何把容器中小于3的值删去
vector<int>coll = {1,2,3,4,3,1,5};
copy(coll.begin(),coll.end(),ostream_iterator<int>(cout," "));
cout << endl;
coll.erase(remove_if(coll.begin(),coll.end(),bind2nd(less<int>(),3)),coll.end());
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
remove_if函数与remove函数类似,区别在于第三参数传入一个函数指针或仿函数,将满足函数要求的元素覆盖,最后返回一个指向新喻尾的迭代器
值得注意的是less<>()为标准库定义的仿函数,需要两个函数参数,而我们的remove_if的第三参数只要一个函数参数,于是我们使用bind2nd将第二参数绑定为3。那么less<>()内部返回的布尔值由 i<3 表达式来决定,为1则覆盖