C++STL算法篇remove和remove_if

某些算法会变更目标区间的内容,甚至会删除元素。一旦这种情况出现,我们要注意几个特殊的问题。

remove() 移除元素的算法

这个算法的特殊在于,它并不是真的删除了元素,而是遇到要删除的元素时让后继元素去覆盖它

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则覆盖

原创文章 23 获赞 1 访问量 367

猜你喜欢

转载自blog.csdn.net/weixin_44806268/article/details/105555780
今日推荐