set和muliset

set就是數學上的集合——每一個元素最多隻能出現一次。ios

【關於set】
set是關聯式容器。set做爲一個容器也是用來存儲同一數據類型的數據類型,而且能從一個數據集合中取出數據,在set中每一個元素的值都惟一,並且系統能根據元素的值自動進行排序。應該注意的是set中數元素的值不能直接被改變。C++ STL中標準關聯容器set, multiset, map, multimap內部採用的就是一種很是高效的平衡檢索二叉樹:紅黑樹,也稱爲RB樹(Red-Black Tree)。RB樹的統計性能要好於通常平衡二叉樹,因此被STL選擇做爲了關聯容器的內部結構。less

 【關聯型容器概述】ide

在學習序列式容器時,咱們知道,容器中元素的順序都是由程序決定的,程序能夠隨意指定新元素的插入位置,而對於關聯型容器,它的全部元素都是通過排序的,關聯型容器都是有序的。它的每個元素都有一個鍵(key),容器中的元素是按照鍵的取值升序排列的。
關聯型容器內部實現爲一個二叉樹,在二叉樹中,每一個元素都有一個父節點和兩個子節點。左子樹的全部元素都比本身小,右子樹的全部元素都比本身大。函數

    A
   / \
  B   C
 / \    / \
  D E  F G性能

關聯型容器內部結構都是以這種一叉樹結構實現, 這也使得它能夠高效地查找容器中的每個元素,但卻不能實現任意位置的操做。
標準庫提供了四種關聯型容器: set(集合)、multiset(多重集合)、map(映射)、multimap(多重映射),其中set與multiset 包含在頭文件set中,map與multimap包含在頭文件map中。

學習

set與muliset的區別在因而否容許有重複元素,其餘用法都很類似,所以將這兩種容器放在一塊兒進行講解, 接下來咱們就分 別講解集合對象的建立及其經常使用的操做方法。spa

【set、muliset中經常使用的方法】
一、建立對象。code

set與muliset中都重載了不一樣的構造函數,所以能夠以不一樣的方式定義集合,set 集合的定義方式以下所示:
set<T> s;          //建立一個空的set集合,默認升序排列
set<T, op> s;        //建立一個空的set集合,按op規則排序
set<T> s(begin, end) ;     //建立一個集合,用[begin, end]區間爲其 初始化
set<T,op> s (begin, end) ;    //建立集合,用[begin, end]區間爲其初始化並按op規則排序
set<T> s(s1) ;       //建立一個空的set集合,用另外一個集合s1初始化對象

set集合提供了五種重載構造函數,接下來咱們分別用這五種方式定義不一樣的集合,代碼
以下所示:
set<char> s1;
set<int, greater<int>()> s2;
set<float> s3(begin, end) ;
set<string,greater<string>()> s4 (begin, end) ;
set<int> s5(s2) ;
注:
geater<T>從大到小
less<T> 從小到大blog

上述代碼分別用不一樣的方式定義了char、int等類型的集合,其中集合s2與s4中greater<T>則是排序規則,意指從大到小的順序排列,若是沒有排序規則,則默認規則是less<T>,意爲從小到大排序,這是STL中定義的函數對象( functor),包含在頭文件functional
與set集合同樣,multiet也重載了這五種構造函數,接下來用這五種方式分別定史不一樣的multiset集合對象,代碼以下所示:

multiset <char> ms1 ;
multiset <int, greater<int> ()> ms2;
multiset <float>ms3 (begin, end) ;
multiset <string, greater<string>()> ms4 (begin, end) ;
multiset <int> ms5(s2) ;

上述代碼分別用五種不一樣的方式定義了五個multiset 集合對象,其定義中的參數與set集合同樣,這裏就再也不贅述。

二、集合的大小,元素的查找和統計。

s.size();              //返回容器中元素的數目
s.max_size();       //返回容器中可容納的最大元素數量
s.empty();      //判斷容器是否爲空

上述函數 調用中的s指集合容器,如無特殊說明,則s既能夠是set容器也能夠是multiset容器,即兩個容器都提供了這樣的函數。

s.find();      //查找函數

s.count();      //統計個數的函數

find( )函數的功能是返回key元素的位置,返回值是迭代器類型。count( )函數的功能是返回元素elem的個數,對於set集合來講,要麼是0要麼是1,而對於multiset來講,值可能大於1。

三、獲取頭尾部元素。

s.begin();     //返回容器中收元素的位置
s.end();      //返回容器中最後一個元素字後的迭代器

 

四、插入和刪除元素。

s.insert(elem);     //在容器中插入元素elem
s.insert(pos, elem);    //在pos位置插入元素elem
s.insert(begin, end);    //在容器中插入[begin,end]區間的值

對於set容器來講,第一種形式的insert( )調用的返回值是pair<iterator, bool>對象,其第一個參數iterator 是迭代器,指示元素插入的位置;第二個參數bool類型的值表明元素是否插入成功。

這是由於set容器中不容許存在重複的元素,若是要插入一個容器中已存在的元素,則插入操做會失敗,而pair中的bool值就是標識插入是否成功,而multiset不存在這樣的狀況,所以multiset返回的是-個 iterator。

set與multiset提供的erase( )函數也有幾種實現形式,其函數調用形式以下所示:

s.erase (pos) ;          //刪除pos位置上的元素
s.erase (begin, end) ;    //刪除[begin, end) 區間上的元素
s.erase (elem) ;      / /刪除元素elem
調用erase()函數能夠刪除某一個位置 上的元素,能夠刪除指定的元素,也能夠刪除指定範圍的元素。

五、其餘

equal_range() 返回一對定位器,分別表示第一個大於或等於給定關鍵值的元素和 第一個大於給定關鍵值的元素,這個返回值是一個pair類型,若是這一對定位器中哪一個返回失敗,就會等於end()的值。具體這個有什麼用途我還沒遇到過~~~
find() ,返回給定值值得定位器,若是沒找到則返回end()。
lower_bound(key_value) ,返回第一個大於等於key_value的定位器
upper_bound(key_value),返回最後一個大於等於key_value的定位器


【示例代碼】

 1 #include <iostream>
 2 #include <set>
 3 #include <functional>
 4 using namespace std;  5 int main()  6 {  7     set<int, greater<int>> s;  //建立一個set容器,元素按降序排列
 8     multiset<char> ms;  //建立一個multiset容器
 9     cout << "s能容納的最大元素數量" << s.max_size() << endl; 10     cout << "ms能容納的最大元素數量" << ms.max_size() << endl; 11     //向s中插入元素
12     pair<set<int>::iterator, bool> ps; 13     ps = s.insert(12); 14     if (ps.second == true) 15         cout << "insert success" << endl; 16     s.insert(39); 17     s.insert(32); 18     s.insert(26); 19     //向ms中插入元素
20     ms.insert('a'); 21     ms.insert('z'); 22     ms.insert('T'); 23     ms.insert('u'); 24     ms.insert('u'); 25     //輸出兩個容器中的元素
26     set<int>::iterator its; //建立s容器的迭代器,用於獲取元素
27     cout << "s容器中元素:"; 28     for (its = s.begin(); its != s.end(); its++) 29         cout << *its << " "; 30     cout << endl; 31     multiset<char>::iterator itms;  //建立ms容器的迭代器
32     cout << "ms容器中元素:"; 33     for (itms = ms.begin(); itms != ms.end(); itms++) 34         cout << *itms << " "; 35     cout << endl; 36 
37     //查找兩個容器中頭尾元素
38     cout << "s頭元素: " << *s.begin() << endl; 39     cout << "ms尾元素: " << *(--ms.end()) << endl; 40     //查找ms容器中u元素出現的次數
41     cout << "ms容器中u元素出現的次數:" << ms.count('u') << endl; 42     system("pause"); 43     return 0; 44 }

運行結果以下

 

樣例中建立了一個set容器s和一個multiset容器ms,其中容器s中的元素是按降序排列,代碼9~ 10行調用max_ size( )函數分別算出兩個容器的最大容量,代碼12~24行分別調用insert( )函數向兩個容器中插入元素,其中ms容器中插入了重複的元素u,代碼26~35行分別建立相應的迭代器輸出容器中的元素,由圖8-14可知,s中的元素按降序排列,ms中的元素按升序排列。代碼37~ 38行分別調用begin()與end( )函數輸出s的頭元素和ms的尾元素,由運行結果可知,兩個元素輸出成功。代碼41行調用count( )函數輸出ms容器中u元素的個數,由運行結果可知,ms容器中u元素有兩個。

 

 

 最後咱們用一到題來體會set的用處。

【問題描述】輸入一個文本,找出全部不一樣的單詞(連續的字母序列),按字典序從小到大輸出。單詞不區分大小寫。

【樣例輸入】

Adventures in Disneyland

Two blondes were going to Disneyland when they came to a fork in the
road. The sign read: "Disneyland Left."

So they went home.

 

【樣例輸出】

a
adventures
blondes
came
disneyland
fork
going
home
in
left
read
road
sign
so
the
they
to
two
went
were
when

【代碼以下】

 1 #include<iostream>
 2 #include<string>
 3 #include<set>
 4 #include<sstream>//stringstream要包含的頭文件
 5 using namespace std;  6 set<string> dict;//string 集合
 7 
 8 int main()  9 { 10 
11     string s, buf; 12     while (cin >> s) 13  { 14         for (int i = 0; i < s.length(); i++) 15             if (isalpha(s[i]))//是不是字母
16                 s[i] = tolower(s[i]);//變成小寫
17             else
18                 s[i] = ' '; 19  stringstream ss(s); 20         //stringstream是字符串流。 21         //它將流與存儲在內存中的string對象綁定起來。 22         //在多種數據類型之間實現自動格式化。
23         while (ss >> buf) 24             dict.insert(buf);//插入元素
25  } 26     for (set<string>::iterator it = dict.begin(); it != dict.end(); ++it)//循環輸出
27         cout << *it << "\n"; 28 
29     system("pause"); 30     return 0; 31 }
View Code
相關文章
相關標籤/搜索