STL:set的使用
關於set
set是以特定的順序儲存相異元素的容器。
set是關聯式容器,C++ STL中標準關聯容器set, multiset, map, multimap內部採用的就是一種非常高效的平衡檢索二叉樹:紅黑樹,也成為RB樹(Red-Black Tree)。RB樹的統計效能要好於一般平衡二叉樹,所以被STL選擇作為了關聯容器的內部結構。
查詢、插入、刪除的時間複雜度都是O(logn)
一些特點:
1、在插入或賦初值時會自動排序(除非是unordered_set)
2、不能直接改變元素值,因為那樣會打亂原本正確的順序,要改變元素值必須先刪除舊元素,則插入新元素
3、不提供直接存取元素的任何操作函式,只能通過迭代器進行間接存取,而且從迭代器角度來看,元素值是常數
4、每次insert或者erase之後,以前儲存的iterator不會失效(關聯式容器,只改變了一些指標的指向,原指標指向的記憶體沒變)(當然,直接erase儲存的指標肯定改變了)
set中的模板函式
begin() 返回指向第一個元素的迭代器
end() 返回指向最後一個元素的後一個位置的迭代器
clear() 清空內容
size() 返回當前元素個數
count(key_value) 用來查詢set中某個鍵值出現的次數,在set只可能為0或1
erase(key_value) 刪除鍵值為key_value的元素
erase(iterator) 刪除迭代器iterator指向的元素
erase(first,second) 刪除迭代器first和second之間的元素,[first,second)
find(key_value) 返回指向key_value的迭代器,如果沒有找到返回end()
insert(key_value)
lower_bound(key_value) 返回第一個大於等於key_value的迭代器
upper_bound(key_value) 返回第一個大於key_value的迭代器
equal_range(key_value) 返回一對迭代器,first等同於lower_bound,second_bound等同於upper_bound,即 [lower_bound,upper_bound)
//若set<int>a,b; vector<int>c
set_union(a.begin(),a.end(),b.begin(),b.end(),back_insert(c)) 並集
set_intersection(a.begin(),a.end(),b.begin(),b.end(),back_insert(c)) 交集
set_difference(a.begin(),a.end(),b.begin(),b.end(),back_insert(c)) 差集
set_symmetric_difference(a.begin(),a.end(),b.begin(),b.end(),back_insert(c)) 對稱差
//使用例項
//初始化set
//這個參考資料好少啊,自己嘗試了這幾種
1 #include<cstdio>
2 #include<set>
3 using namespace std;
4
5 int main()
6 {
7 int arr[] = { 3,2,1,4,5 };
8
9 //定義時賦初值
10 set<int>st1{3,2,1,4,5};
11 set<int>st2 = { 3,2,1,4,5 };
12 set<int>st3(arr, arr + 5);
13
14 //先定義,後賦值
15 set<int>st4;
16 st4 = { 3,2,1,4,5 };
17 set<int>st5;
18 st5.insert(arr, arr + 5);
19
20 return 0;
21 }
//基本操作
1 #include<cstdio>
2 #include<set>
3 using namespace std;
4
5 int main()
6 {
7 int arr[] = { 8, 10, 3, 3, 4, 3, 2, 1 };
8 set<int>st(arr,arr + 8);
9
10 //遍歷
11 //不像vector,只能通過迭代器進行間接存取
12 for (set<int>::iterator it = st.begin(); it != st.end(); it++)
13 printf("%d ", *it);
14 printf("\n");
15
16 //查詢
17 //未找到返回end()
18 set<int>::iterator it = st.find(4);
19 if(it != st.end()) printf("%d\n", *it);
20
21 //插入
22 //返回值為pair<set<int>::iterator,bool>
23 st.insert(0); st.insert(5);
24
25 //刪除
26 //不要去刪除不存在的元素
27 st.erase(3); st.erase(11);
28
29 //計數,是否在集合中
30 if (st.count(3)) printf("In\n");
31 else printf("Out\n");
32
33 //上下界函式
34 set<int>::iterator it1 = st.lower_bound(10);
35 set<int>::iterator it2 = st.upper_bound(10);
36
37 //區間定位
38 pair<set<int>::const_iterator, set<int>::const_iterator>pr;
39 pr = st.equal_range(8);
40 if(pr.second != st.end()) printf("%d %d\n", *pr.first, *pr.second);
41
42 for (set<int>::iterator it = st.begin(); it != st.end(); it++)
43 printf("%d ", *it);
44 return 0;
45 }
//集合操作
1 #include<cstdio>
2 #include<set>
3 #include<vector>
4 #include<iterator> //inserter函式定義在裡面
5 #include<algorithm> //set_union,set_intersection等定義在裡面
6 using namespace std;
7
8
9 int main()
10 {
11 //若待處理的集合用vecter儲存,必須確保無重複且有序
12 //若用vector儲存結果,使用函式back_inserter(dest)
13 vector<int>v1 = { 1,3,4,5,7,10 };
14 vector<int>v2 = { 1,5,6,7,8,10,15 };
15 vector<int>dest1;
16 set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(dest1));
17 //set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(dest));
18 //set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(dest));
19 //set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(dest));
20
21 //若用set儲存結果,使用函式inserter(dest,dest.begin())
22 set<int>dest2;
23 set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), inserter(dest2, dest2.begin()));
24
25 //若待處理的集合用set儲存,可以無序重複(會自動去重、排序)
26 set<int>s1 = { 10,3,3,3,4,4,5,7,1 };
27 set<int>s2 = { 1,5,6,7,8,10,15 };
28 set<int>dest3;
29 set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), inserter(dest3, dest3.begin()));
30
31 return 0;
32 }
參考資料:
1、http://www.cplusplus.com/reference/set/set/?kw=set
2、https://blog.csdn.net/changjiale110/article/details/79108447
3、https://blog.csdn.net/rocky_56X/article/details/81772646
4、https://blog.csdn.net/yang20141109/article/details/51782027