C++中 set(集合容器)的用法


set集合容器:

  實現了紅黑樹(Red-Black Tree)的平衡二叉檢索樹的數據結構,在插入元素時,

它會自動調整二叉樹的排列,把該元素放到適當的位置,以確保每個子樹根節點的鍵值大於左子樹所有節點的鍵值,

而小於右子樹所有節點的鍵值;另外,還得確保根節點的左子樹的高度與有字數的高度相等,

這樣,二叉樹的高度最小,從而檢索速度最快。要注意的是,它不會重復插入相同鍵值的元素,而采取忽略處理。

  平衡二叉檢索樹的檢索使用中序遍歷算法,檢索效率高於vector、deque、和list的容器。

另外,采用中序遍歷算法可將鍵值由小到大遍歷出來,所以,可以理解為平衡二叉檢索樹在插入元素時,

就會自動將元素按鍵值從小到大的順序排列。

     構造set集合的主要目的是為了快速檢索,使用set前,需要在程序頭文件中包含聲明“#include<set>”。

 

c++ stl集合(Set):

  是一種包含已排序對象的關聯容器。set/multiset會根據待定的排序准則,

  自動將元素排序。兩者不同在於前者不允許元素重復,而后者允許。

  1) 不能直接改變元素值,因為那樣會打亂原本正確的順序,要改變元素值必須先刪除舊元素,則插入新元素

  2) 不提供直接存取元素的任何操作函數,只能通過迭代器進行間接存取,而且從迭代器角度來看,元素值是常數

  3) 元素比較動作只能用於型別相同的容器(即元素和排序准則必須相同)

 

set的各成員函數列表如下:

begin()--返回指向第一個元素的迭代器

 clear()--清除所有元素

 count()--返回某個值元素的個數

 empty()--如果集合為空,返回true

 end()--返回指向最后一個元素的迭代器

 equal_range()--返回集合中與給定值相等的上下限的兩個迭代器

 erase()--刪除集合中的元素

 find()--返回一個指向被查找到元素的迭代器

 get_allocator()--返回集合的分配器

 insert()--在集合中插入元素

 lower_bound()--返回指向大於(或等於)某值的第一個元素的迭代器

 key_comp()--返回一個用於元素間值比較的函數

 max_size()--返回集合能容納的元素的最大限值

 rbegin()--返回指向集合中最后一個元素的反向迭代器

 rend()--返回指向集合中第一個元素的反向迭代器

 size()--集合中元素的數目

 swap()--交換兩個集合變量

 upper_bound()--返回大於某個值元素的迭代器

 value_comp()--返回一個用於比較元素間的值的函數

 

1.創建set集合對象

           創建set對象時,需要指定元素的類型,這一點和其他容器一樣。

1 #include<iostream>  
2 #include<set>  
3 using namespace std;  
4 int main()  
5 {  
6     set<int> s;  
7     return 0;  
8 } 

2.元素的插入與中序遍歷

        采用inset()方法把元素插入到集合中,插入規則在默認的比較規則下,

是按元素值從小到大插入,如果自己指定了比較規則函數,則按自定義比較規則函數插入。

使用前向迭代器對集合中序遍歷,結果正好是元素排序后的結果。

 1 #include<iostream>  
 2 #include<set>  
 3 using namespace std;  
 4 int main()  
 5 {  
 6     set<int> s;  
 7     s.insert(5); //第一次插入5,可以插入  
 8     s.insert(1);  
 9     s.insert(6);  
10     s.insert(3);  
11     s.insert(5); //第二次插入5,重復元素,不會插入  
12     set<int>::iterator it; //定義前向迭代器  
13     //中序遍歷集合中的所有元素  
14     for(it = s.begin(); it != s.end(); it++)  
15     {  
16         cout << *it << " ";  
17     }  
18     cout << endl;  
19     return 0;  
20 }  
21 //運行結果:1 3 5 6 

3.元素的方向遍歷

        使用反向迭代器reverse_iterator可以反向遍歷集合,輸出的結果正好是集合元素的反向排序結果。

    它需要用到rbegin()和rend()兩個方法,它們分別給出了反向遍歷的開始位置和結束位置。

 1 #include<iostream>  
 2 #include<set>  
 3 using namespace std;  
 4 int main()  
 5 {  
 6     set<int> s;  
 7     s.insert(5); //第一次插入5,可以插入  
 8     s.insert(1);  
 9     s.insert(6);  
10     s.insert(3);  
11     s.insert(5); //第二次插入5,重復元素,不會插入  
12     set<int>::reverse_iterator rit; //定義反向迭代器  
13     //反向遍歷集合中的所有元素  
14     for(rit = s.rbegin(); rit != s.rend(); rit++)  
15     {  
16         cout << *rit << " ";  
17     }  
18     cout << endl;  
19     return 0;  
20 }  
21 //運行結果:6 5 3 1 

4.元素的刪除

        與插入元素的處理一樣,集合具有高效的刪除處理功能,並自動重新調整內部的紅黑樹的平衡。

    刪除的對象可以是某個迭代器位置上的元素、等於某鍵值的元素、一個區間上的元素和清空集合。

 1 #include<iostream>  
 2 #include<set>  
 3 using namespace std;  
 4 int main()  
 5 {  
 6     set<int> s;  
 7     s.insert(5); //第一次插入5,可以插入  
 8     s.insert(1);  
 9     s.insert(6);  
10     s.insert(3);  
11     s.insert(5); //第二次插入5,重復元素,不會插入  
12     s.erase(6); //刪除鍵值為6的元素  
13     set<int>::reverse_iterator rit; //定義反向迭代器  
14     //反向遍歷集合中的所有元素  
15     for(rit = s.rbegin(); rit != s.rend(); rit++)  
16     {  
17         cout << *rit << " ";  
18     }  
19     cout << endl;   
20     set<int>::iterator it;  
21   
22     it = s.begin();  
23     for(int i = 0; i < 2; i++)  
24         it = s.erase(it);   
25     for(it = s.begin(); it != s.end(); it++)  
26         cout << *it << " ";  
27     cout << endl;  
28   
29     s.clear();  
30     cout << s.size() << endl;  
31   
32     return 0;  
33 }  
34 /* 
35 運行結果: 
36 5 3 1 
37 5 
38 0     
39 */ 

5.元素的檢索

          使用find()方法對集合進行檢索,如果找到查找的的鍵值,則返回該鍵值的迭代器位置;

     否則,返回集合最后一個元素后面的一個位置,即end()。

 1 #include<iostream>  
 2 #include<set>  
 3 using namespace std;  
 4 int main()  
 5 {  
 6     set<int> s;  
 7     s.insert(5); //第一次插入5,可以插入  
 8     s.insert(1);  
 9     s.insert(6);  
10     s.insert(3);  
11     s.insert(5); //第二次插入5,重復元素,不會插入  
12     set<int>::iterator it;  
13     it = s.find(6); //查找鍵值為6的元素  
14     if(it != s.end())  
15         cout << *it << endl;  
16     else  
17         cout << "not find it" << endl;  
18     it = s.find(20);  
19     if(it != s.end())  
20         cout << *it << endl;  
21     else  
22         cout << "not find it" << endl;  
23     return 0;  
24 }  
25 /* 
26 運行結果: 
27 6 
28 not find it    
29 */  

下面這種方法也能判斷一個數是否在集合中:

 1 #include <cstdio>  
 2 #include <set>  
 3 using namespace std;  
 4 int main() {  
 5     set <int> s;  
 6     int a;  
 7     for(int i = 0; i < 10; i++)  
 8         s.insert(i);  
 9     for(int i = 0; i < 5; i++) {  
10         scanf("%d", &a);  
11         if(!s.count(a)) //不存在  
12             printf("does not exist\n");  
13         else  
14             printf("exist\n");  
15     }  
16     return 0;  
17 }  

6.自定義比較函數

         使用insert將元素插入到集合中去的時候,集合會根據設定的比較函數獎該元素放到該放的節點上去。

在定義集合的時候,如果沒有指定比較函數,那么采用默認的比較函數,即按鍵值從小到大的順序插入元素。

但在很多情況下,需要自己編寫比較函數。

 

編寫比較函數有兩種方法。

(1)如果元素不是結構體,那么可以編寫比較函數。下面的程序比較規則為按鍵值從大到小的順序插入到集合中。

 1 #include<iostream>  
 2 #include<set>  
 3 using namespace std;  
 4 struct mycomp  
 5 { //自定義比較函數,重載“()”操作符  
 6     bool operator() (const int &a, const int &b)  
 7     {  
 8         if(a != b)  
 9             return a > b;  
10         else  
11             return a > b;  
12     }  
13 };  
14 int main()  
15 {  
16     set<int, mycomp> s; //采用比較函數mycomp  
17     s.insert(5); //第一次插入5,可以插入  
18     s.insert(1);  
19     s.insert(6);  
20     s.insert(3);  
21     s.insert(5); //第二次插入5,重復元素,不會插入  
22     set<int,mycomp>::iterator it;  
23     for(it = s.begin(); it != s.end(); it++)  
24         cout << *it << " ";  
25     cout << endl;  
26     return 0;  
27 }  
28 /* 
29 運行結果:6 5 3 1   
30 */ 

(2)如果元素是結構體,那么可以直接把比較函數寫在結構體內。

 1 #include<iostream>  
 2 #include<set>  
 3 #include<string>  
 4 using namespace std;  
 5 struct Info  
 6 {  
 7     string name;  
 8     double score;  
 9     bool operator < (const Info &a) const // 重載“<”操作符,自定義排序規則  
10     {  
11         //按score由大到小排序。如果要由小到大排序,使用“>”即可。  
12         return a.score < score;  
13     }  
14 };  
15 int main()  
16 {  
17     set<Info> s;  
18     Info info;  
19   
20     //插入三個元素  
21     info.name = "Jack";  
22     info.score = 80;  
23     s.insert(info);  
24     info.name = "Tom";  
25     info.score = 99;  
26     s.insert(info);  
27     info.name = "Steaven";  
28     info.score = 60;  
29     s.insert(info);  
30   
31     set<Info>::iterator it;  
32     for(it = s.begin(); it != s.end(); it++)  
33         cout << (*it).name << " : " << (*it).score << endl;   
34     return 0;  
35 }  
36 /* 
37 運行結果: 
38 Tom : 99 
39 Jack : 80 
40 Steaven : 60 
41 */  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM