原文网址:http://blog.csdn.net/nowen/article/details/5509525
需要这样一个容器,可以自动地删除重复元素,并能很方便地进行查找操作!
似乎采用树型结构存储的std::set是最佳之选,但到后面才发现,存进去容易,取出来麻烦。不得已又回去用std::vector,就在网上找了找,vector是如何实现类似set的unique和find的。其实也没有想象的复杂,也不需要死去套循环~
vector删除重复元素
主要思路为,先排序,再唯一,然后删除最后面的那段重复代码。
举例:有这样一个vector
int a[10] = {1,3,6,4,7,2,3,4,8,9}; // 1,2,3,3,4,4,6,7,8,9
vector<int> ivec(a, a+10);
①首先将vector排序
sort( vecSrc.begin(), vecSrc.end() ); // 1,2,3,3,4,4,6,7,8,9
②然后使用unique算法,unique返回值是重复元素的开始位置。
vector<int>::iter pos;
pos = unique(ivec.begin, ivec.end()); //1,2,3,4,6,7,8,9,3,4
// ^
③最后删除后面的那段重复部分
earse(pos, ivec.end()); //1,2,3,4,6,7,8,9
如果vector中存储的元素是自定义的结构或者是类,那么就需要重载操作符。根据类的某一个成员变量排序或者比较。
sort算法需要重载"<"操作符。unique算法需要重载"=="操作符。
操作符重载的示例如下:
class CTest
……
public:
BOOL operator<( const CTest& oCompany ) const
{
return this->m_nCompanyId < oCompany.m_nCompanyId;
}
BOOL operator==( const CECompany& oCompany ) const
{
return this->m_nCompanyId == oCompany.m_nCompanyId;
}
}
另外一种方法是使用unique_copy
Example
// unique_copy example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool myfunction (int i, int j) {
return (i==j);
}
int main () {
int myints[] = {10,20,20,20,30,30,20,20,10};
vector<int> myvector (9); // 0 0 0 0 0 0 0 0 0
vector<int>::iterator it;
// using default comparison:
it=unique_copy (myints,myints+9,myvector.begin()); // 10 20 30 20 10 0 0 0 0
// ^
sort (myvector.begin(),it); // 10 10 20 20 30 0 0 0 0
// ^
// using predicate comparison:
it=unique_copy (myvector.begin(), it, myvector.begin(), myfunction);
// 10 20 30 20 30 0 0 0 0
// ^
myvector.resize( it - myvector.begin() ); // 10 20 30
// print out content:
cout << "myvector contains:";
for (it=myvector.begin(); it!=myvector.end(); ++it)
cout << " " << *it;
cout << endl;
return 0;
}
Output:
myvector contains: 10 20 30
vector元素查找
如果vector的元素是一个简单的类型如int时,
可按下面方法查找元素:
vector<int> x;
x.push_back(33);
x.push_back(532);
x.push_back(222);
vector<int>::iterator iter;
iter = find(x.begin(), x.end(), 532);
但如果是一个类时,如何查找呢?
方法1:
重载operator(),也就是用functor(对象)
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
class A
{
public:
int id;
char name[32];
A(int _id, char *_name)
{
id = _id;
strcpy(name, _name);
}
~A() {};
};
class A_id_equ :public unary_function<A,bool>
{
public:
int i;
explicit A_id_equ(const int s): i(s){}
bool operator ()(const A& e){return e.id==i;}
};
int main()
{
vector<A> x;
A a(18, "fdsaf");
x.push_back(a);
A b(25, "SREW");
x.push_back(b);
A c(300, "htrhgrt");
x.push_back(c);
vector<A>::iterator iter;
iter = find_if(x.begin(), x.end(),A_id_equ(25));
}
方法2:
顺便提醒大家一下,这种小动作最好不要动辄使用functor。functor会导致代码物理分离,可维护性不佳,不然C#3.0干嘛屁颠屁颠地加入lambda算子和匿名函数呢;-)好在C++不要语言级别支持也可以很大程度上实现同样的功能,只需使用boost::bind boost::lambda等functional库即可。话说回来,使用lambda这样的类一旦走火,后果不堪设想,你会看到排山倒海的错误信息,所以甚用,不过boost::bind还是不错的,况且已经加入TR1,可以放心大胆用,有标准给你撑腰;-)
--pongba(刘未鹏|http://blog.csdn.net/pongba)
#include <algorithm>
#include <vector>
#include <boost/bind.hpp>
struct A
{
int id;
};
int main()
{
using namespace std;
using namespace boost;
vector<A> v;
find_if(v.begin(),v.end(),bind(&A::id,_1)==25);
}