需要這樣一個容器,可以自動地刪除重複元素,並能很方便地進行查找操作!
似乎採用樹型結構存儲的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);
}
如果你不知道boost是什麼,見 http://www.boost.org