set是STL中一種標準關聯容器(vector,list,string,deque都是序列容器,而set,multiset,map,multimap是標準關聯容器),它底層使用平衡的搜索樹——紅黑樹實現,插入刪除操做時僅僅須要指針操做節點便可完成,不涉及到內存移動和拷貝,因此效率比較高。set,顧名思義是「集合」的意思,在set中元素都是惟一的,並且默認狀況下會對元素自動進行升序排列,支持集合的交(set_intersection),差(set_difference) 並(set_union),對稱差(set_symmetric_difference) 等一些集合上的操做,若是須要集合中的元素容許重複那麼可使用multisetios
#include<set> #include<iterator> #include<iostream> using namespace std; int main() { set<int>eg1; //插入 eg1.insert(1); eg1.insert(100); eg1.insert(5); eg1.insert(1);//元素1由於已經存在因此set中不會再次插入1 eg1.insert(10); eg1.insert(9); //遍歷set,能夠發現元素是有序的 set<int>::iterator set_iter=eg1.begin(); cout<<"Set named eg1:"<<endl; for(;set_iter!=eg1.end();set_iter++) cout<<*set_iter<<" "; cout<<endl; //使用size()函數能夠得到當前元素個數 cout<<"Now there are "<<eg1.size()<<" elements in the set eg1"<<endl; if(eg1.find(200)==eg1.end())//find()函數能夠查找元素是否存在 cout<<"200 isn't in the set eg1"<<endl; set<int>eg2; for(int i=6;i<15;i++) eg2.insert(i); cout<<"Set named eg2:"<<endl; for(set_iter=eg2.begin();set_iter!=eg2.end();set_iter++) cout<<*set_iter<<" "; cout<<endl; //得到兩個set的並 set<int>eg3; cout<<"Union:"; set_union(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin()));//注意第五個參數的形式 copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," ")); cout<<endl; //得到兩個set的交,注意進行集合操做以前接收結果的set要調用clear()函數清空一下 eg3.clear(); set_intersection(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin())); cout<<"Intersection:"; copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," ")); cout<<endl; //得到兩個set的差 eg3.clear(); set_difference(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin())); cout<<"Difference:"; copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," ")); cout<<endl; //得到兩個set的對稱差,也就是假設兩個集合分別爲A和B那麼對稱差爲AUB-A∩B eg3.clear(); set_symmetric_difference(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin())); copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," ")); cout<<endl; return 0; }
set會對元素進行排序,那麼問題也就出現了排序的規則是怎樣的呢?上面的示例代碼咱們發現對int型的元素能夠自動判斷大小順序,可是對char*就不會自動用strcmp進行判斷了,更別說是用戶自定義的類型了,事實上set的標準形式是set<Key, Compare, Alloc>,less
參數 | 描述 | 默認值 |
---|---|---|
Key | 集合的關鍵字和值的類型 | |
Compare | 關鍵字比較函數,它的參數類型key參數指定的類型,若是第一個參數小於第二個參數則返回true,不然返回false | less<Key> |
Alloc | set的分配器,用於內部內存管理 | alloc |
下面給出一個關鍵字類型爲char*的示例代碼函數
#include<iostream> #include<iterator> #include<set> using namespace std; struct ltstr { bool operator() (const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; int main() { const int N = 6; const char* a[N] = {"isomer", "ephemeral", "prosaic", "nugatory", "artichoke", "serif"}; const char* b[N] = {"flat", "this", "artichoke", "frigate", "prosaic", "isomer"}; set<const char*,ltstr> A(a, a + N); set<const char*,ltstr> B(b, b + N); set<const char*,ltstr> C; cout << "Set A: "; //copy(A.begin(), A.end(), ostream_iterator<const char*>(cout, " ")); set<const char*,ltstr>::iterator itr; for(itr=A.begin();itr!=A.end();itr++) cout<<*itr<<" "; cout << endl; cout << "Set B: "; copy(B.begin(), B.end(), ostream_iterator<const char*>(cout, " ")); cout << endl; cout << "Union: "; set_union(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator<const char*>(cout, " "), ltstr()); cout << endl; cout << "Intersection: "; set_intersection(A.begin(), A.end(), B.begin(),B.end(),ostream_iterator<const char*>(cout," "),ltstr()); cout<<endl; set_difference(A.begin(), A.end(), B.begin(), B.end(),inserter(C, C.begin()),ltstr()); cout << "Set C (difference of A and B): "; copy(C.begin(), C.end(), ostream_iterator<const char*>(cout, " ")); cout <<endl; return 0; }
其中的ltstr也能夠這樣定義this
class ltstr { public: bool operator() (const char* s1,const char*s2)const { return strcmp(s1,s2)<0; } };
更加通用的應用方式那就是數據類型也是由用戶自定義的類來替代,比較的函數自定義,甚至能夠加上二級比較,好比首先按照總分數排序,對於分數相同的按照id排序,下面是示例代碼spa
#include<set> #include<iostream> using namespace std; struct Entity { int id; int score; string name; }; struct compare { bool operator()(const Entity& e1,const Entity& e2)const { if(e1.score<e2.score) return true; else if(e1.score==e2.score) if(e1.id<e2.id) return true; return false; } }; int main() { set<Entity,compare>s_test; Entity a,b,c; a.id=123;a.score=90;a.name="bill"; b.id=121;b.score=85;b.name="mary"; c.id=130;c.score=85;c.name="jerry"; s_test.insert(a);s_test.insert(b);s_test.insert(c); set<Entity,compare>::iterator itr; cout<<"Score List(ordered by score):\n"; for(itr=s_test.begin();itr!=s_test.end();itr++) cout<<itr->id<<"---"<<itr->name<<"---"<<itr->score<<endl; return 0; }