c++ stl集合set介紹 c++ stl集合(Set)是一種包含已排序對象的關聯容器。
set/multiset會根據待定的排序准則,自動將元素排序。兩者不同在於前者不允許元素重復,而后者允許。
c++ stl集合set介紹
c++ stl集合(Set)是一種包含已排序對象的關聯容器。set/multiset會根據待定的排序准則,自動將元素排序。兩者不同在於前者不允許元素重復,而后者允許。
1) 不能直接改變元素值,因為那樣會打亂原本正確的順序,要改變元素值必須先刪除舊元素,則插入新元素
2) 不提供直接存取元素的任何操作函數,只能通過迭代器進行間接存取,而且從迭代器角度來看,元素值是常數
3) 元素比較動作只能用於型別相同的容器(即元素和排序准則必須相同)
set模板原型://Key為元素(鍵值)類型
1
|
template
<
class
Key,
class
Compare=less<Key>,
class
Alloc=STL_DEFAULT_ALLOCATOR(Key) >
|
從原型可以看出,可以看出比較函數對象及內存分配器采用的是默認參數,因此如果未指定,它們將采用系統默認方式。
set的各成員函數列表如下:
c++ stl容器set成員函數:begin()--返回指向第一個元素的迭代器
c++ stl容器set成員函數:clear()--清除所有元素
c++ stl容器set成員函數:count()--返回某個值元素的個數
c++ stl容器set成員函數:empty()--如果集合為空,返回true
c++ stl容器set成員函數:end()--返回指向最后一個元素的迭代器
c++ stl容器set成員函數:equal_range()--返回集合中與給定值相等的上下限的兩個迭代器
c++ stl容器set成員函數:erase()--刪除集合中的元素
c++ stl容器set成員函數:find()--返回一個指向被查找到元素的迭代器
c++ stl容器set成員函數:get_allocator()--返回集合的分配器
c++ stl容器set成員函數:insert()--在集合中插入元素
c++ stl容器set成員函數:lower_bound()--返回指向大於(或等於)某值的第一個元素的迭代器
c++ stl容器set成員函數:key_comp()--返回一個用於元素間值比較的函數
c++ stl容器set成員函數:max_size()--返回集合能容納的元素的最大限值
c++ stl容器set成員函數:rbegin()--返回指向集合中最后一個元素的反向迭代器
c++ stl容器set成員函數:rend()--返回指向集合中第一個元素的反向迭代器
c++ stl容器set成員函數:size()--集合中元素的數目
c++ stl容器set成員函數:swap()--交換兩個集合變量
c++ stl容器set成員函數:upper_bound()--返回大於某個值元素的迭代器
c++ stl容器set成員函數:value_comp()--返回一個用於比較元素間的值的函數
常用操作:
1.元素插入:insert()
2.中序遍歷:類似vector遍歷(用迭代器)
3.反向遍歷:利用反向迭代器reverse_iterator。
例:
1 set<int> s; 2 ...... 3 set<int>::reverse_iterator rit; 4 for(rit=s.rbegin();rit!=s.rend();rit++)
4.元素刪除:與插入一樣,可以高效的刪除,並自動調整使紅黑樹平衡。
1 set<int> s; 2 s.erase(2); //刪除鍵值為2的元素 3 s.clear();
5.元素檢索:find(),若找到,返回該鍵值迭代器的位置,否則,返回最后一個元素后面一個位置。
1 set<int> s; 2 set<int>::iterator it; 3 it = s.find(5); //查找鍵值為5的元素 4 if (it != s.end()) //找到 5 cout << *it << endl; 6 else //未找到 7 cout << "未找到";
6.自定義比較函數
(1)元素不是結構體:
例:
//自定義比較函數myComp,重載“()”操作符
1 struct myComp 2 { 3 bool operator()(const your_type &a, const your_type &b){ 4 return a.data - b.data > 0; 5 } 6 } 7 set<int, myComp>s; 8 ...... 9 set<int, myComp>::iterator it; erator it;
(2)如果元素是結構體,可以直接將比較函數寫在結構體內。
例:
1 struct Info 2 { 3 string name; 4 float score; 5 //重載“<”操作符,自定義排序規則 6 bool operator < (const Info &a) const 7 { 8 //按score從大到小排列 9 return a.score<score; 10 } 11 } 12 set<Info> s; 13 ...... 14 set<Info>::iterator it;
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 //set插入元素操作 5 int main() 6 { 7 //定義一個int型集合對象s,當前沒有任何元素.由www.169it.com搜集整理 8 set<int> s; 9 s.insert(8); //第一次插入8,可以插入 10 s.insert(1); 11 s.insert(12); 12 s.insert(6); 13 s.insert(8); //第二次插入8,重復元素,不會插入 14 set<int>::iterator it; //定義前向迭代器 15 for(it=s.begin();it!=s.end();it++) 16 cout<<*it<<endl; 17 system("pause"); 18 return 0; 19 }
其他用法如下
1 #include <iostream> 2 #include <iterator> 3 #include <set> 4 #include <algorithm> 5 using namespace std; 6 int main() 7 { 8 set<int> eg1; 9 eg1.insert(1); 10 eg1.insert(100); 11 eg1.insert(5); 12 eg1.insert(1); //元素1因為已經存在所以set中不會再次插入1 13 eg1.insert(10); 14 eg1.insert(9); 15 //遍歷set,可以發現元素是有序的 16 set<int>::iterator set_iter = eg1.begin(); 17 cout << "Set named eg1:" << endl; 18 for (; set_iter != eg1.end(); set_iter++) cout << *set_iter << " "; 19 cout << endl; 20 //使用size()函數可以獲得當前元素個數 21 cout << "Now there are " << eg1.size() << " elements in the set eg1" << endl; 22 if (eg1.find(200) == eg1.end())//find()函數可以查找元素是否存在 23 cout << "200 isn't in the set eg1" << endl; 24 25 26 27 set<int> eg2; 28 for (int i = 6; i < 15; i++) 29 eg2.insert(i); 30 cout << "Set named eg2:" << endl; 31 for (set_iter = eg2.begin(); set_iter != eg2.end(); set_iter++) 32 cout << *set_iter << " "; 33 cout << endl; 34 35 //獲得兩個set的並 36 set<int> eg3; 37 cout << "Union(兩個set的並集):"; 38 set_union(eg1.begin(), 39 eg1.end(), 40 eg2.begin(), 41 eg2.end(), 42 insert_iterator<set<int> >(eg3, eg3.begin()) 43 );//注意第五個參數的形式 44 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 45 cout << endl; 46 47 //獲得兩個set的交,注意進行集合操作之前接收結果的set要調用clear()函數清空一下 48 eg3.clear(); 49 set_intersection(eg1.begin(), 50 eg1.end(), 51 eg2.begin(), 52 eg2.end(), 53 insert_iterator<set<int> >(eg3, eg3.begin()) 54 ); 55 cout << "Intersection:"; 56 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 57 cout << endl; 58 59 //獲得兩個set的差 60 eg3.clear(); 61 set_difference(eg1.begin(), 62 eg1.end(), eg2.begin(), 63 eg2.end(), 64 insert_iterator<set<int> >(eg3, eg3.begin()) 65 ); 66 cout << "Difference:"; 67 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 68 cout << endl; 69 70 //獲得兩個set的對稱差,也就是假設兩個集合分別為A和B那么對稱差為AUB-A∩B 71 eg3.clear(); 72 set_symmetric_difference(eg1.begin(), eg1.end(), eg2.begin(), eg2.end(), insert_iterator<set<int> >(eg3, eg3.begin())); 73 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 74 cout << endl; 75 76 return 0; 77 } 78 79 80 81 下面給出一個關鍵字類型為char*的示例代碼 82 83 #include<iostream> 84 #include<iterator> 85 #include<set> 86 using namespace std; 87 struct ltstr 88 { 89 bool operator() (const char* s1, const char* s2) const 90 { 91 return strcmp(s1, s2) < 0; 92 } 93 }; 94 95 int main() 96 { 97 const int N = 6; 98 const char* a[N] = { "isomer", "ephemeral", "prosaic", 99 "nugatory", "artichoke", "serif" }; 100 const char* b[N] = { "flat", "this", "artichoke", 101 "frigate", "prosaic", "isomer" }; 102 103 set<const char*, ltstr> A(a, a + N); 104 set<const char*, ltstr> B(b, b + N); 105 set<const char*, ltstr> C; 106 107 cout << "Set A: "; 108 //copy(A.begin(), A.end(), ostream_iterator<const char*>(cout, " ")); 109 set<const char*, ltstr>::iterator itr; 110 for (itr = A.begin(); itr != A.end(); itr++) cout << *itr << " "; 111 cout << endl; 112 cout << "Set B: "; 113 copy(B.begin(), B.end(), ostream_iterator<const char*>(cout, " ")); 114 cout << endl; 115 116 cout << "Union: "; 117 set_union(A.begin(), A.end(), B.begin(), B.end(), 118 ostream_iterator<const char*>(cout, " "), 119 ltstr()); 120 cout << endl; 121 122 cout << "Intersection: "; 123 set_intersection(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator<const char*>(cout, " "), ltstr()); 124 cout << endl; 125 set_difference(A.begin(), A.end(), B.begin(), B.end(), inserter(C, C.begin()), ltstr()); 126 cout << "Set C (difference of A and B): "; 127 copy(C.begin(), C.end(), ostream_iterator<const char*>(cout, " ")); 128 cout << endl; 129 return 0; 130 } 131 132 其中的ltstr也可以這樣定義 133 class ltstr 134 { 135 public: 136 bool operator() (const char* s1, const char*s2)const 137 { 138 return strcmp(s1, s2) < 0; 139 } 140 }; 141 142 更加通用的應用方式那就是數據類型也是由用戶自定義的類來替代,比較的函數自定義,甚至可以加上二級比較,比如首先按照總分數排序,對於分數相同的按照id排序,下面是示例代碼 143 144 #include<set> 145 #include<iostream> 146 using namespace std; 147 struct 148 { 149 int id; 150 int score; 151 string name; 152 }; 153 struct compare 154 { 155 bool operator()(const Entity& e1, const Entity& e2)const { 156 if (e1.score < e2.score) return true; 157 else 158 if (e1.score == e2.score) 159 if (e1.id < e2.id) return true; 160 161 return false; 162 } 163 }; 164 165 int main() 166 { 167 set<Entity, compare>s_test; 168 Entity a, b, c; 169 a.id = 123; a.score = 90; a.name = "bill"; 170 b.id = 121; b.score = 85; b.name = "mary"; 171 c.id = 130; c.score = 85; c.name = "jerry"; 172 s_test.insert(a); s_test.insert(b); s_test.insert(c); 173 set<Entity, compare>::iterator itr; 174 cout << "Score List(ordered by score):\n"; 175 for (itr = s_test.begin(); itr != s_test.end(); itr++) 176 cout << itr->id << "---" << itr->name << "---" << itr->score << endl; 177 return 0; 178 }