程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 關於STL中set容器的一些總結

關於STL中set容器的一些總結

編輯:關於C++

關於STL中set容器的一些總結。本站提示廣大學習愛好者:(關於STL中set容器的一些總結)文章只能為提供參考,不一定能成為您想要的結果。以下是關於STL中set容器的一些總結正文


1.關於set

C++ STL 之所以獲得普遍的贊譽,也被許多人應用,不只是供給了像vector, string, list等便利的容器,更主要的是STL封裝了很多龐雜的數據構造算法和年夜量經常使用數據構造操作。vector封裝數組,list封裝了鏈表,map和set封裝了二叉樹等,在封裝這些數據構造的時刻,STL依照法式員的應用習氣,以成員函數方法供給的經常使用操作,如:拔出、排序、刪除、查找等。讓用戶在STL應用進程中,其實不會覺得生疏。

關於set,必需解釋的是set聯系關系式容器。set作為一個容器也是用來存儲統一數據類型的數據類型,而且能從一個數據聚集中掏出數據,在set中每一個元素的值都獨一,並且體系能依據元素的值主動停止排序。應當留意的是set中數元素的值不克不及直接被轉變。C++ STL中尺度聯系關系容器set, multiset, map, multimap外部采取的就是一種異常高效的均衡檢索二叉樹:紅黑樹,同樣成為RB樹(Red-Black Tree)。RB樹的統計機能要好過普通均衡二叉樹,所以被STL選擇作為了聯系關系容器的外部構造。

 關於set有上面幾個成績:

(1)為什麼map和set的拔出刪除效力比用其他序列容器高?

年夜部門人說,很簡略,由於關於聯系關系容器來講,不須要做內存拷貝和內存挪動。說對了,確切如斯。set容器內一切元素都是以節點的方法來存儲,其節點構造和鏈表差不多,指向父節點和子節點。構造圖能夠以下:

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

是以拔出的時刻只須要稍做變換,把節點的指針指向新的節點便可以了。刪除的時刻相似,稍做變換後把指向刪除節點的指針指向其他節點也OK了。這裡的一切操作就是指針換來換去,和內存挪動沒有關系。

(2)為什麼每次insert以後,之前保留的iterator不會掉效?

iterator這裡就相當於指向節點的指針,內存沒有變,指向內存的指針怎樣會掉效呢(固然被刪除的誰人元素自己曾經掉效了)。絕對於vector來講,每次刪除和拔出,指針都有能夠掉效,挪用push_back在尾部拔出也是如斯。由於為了包管外部數據的持續寄存,iterator指向的那塊內存在刪除和拔出進程中能夠曾經被其他內存籠罩或許內存曾經被釋放了。即便時push_back的時刻,容器外部空間能夠不敷,須要一塊新的更年夜的內存,只要把之前的內存釋放,請求新的更年夜的內存,復制已有的數據元素到新的內存,最初把須要拔出的元素放到最初,那末之前的內存指針天然就弗成用了。特殊時在和find等算法在一路應用的時刻,切記這個准繩:不要應用過時的iterator。

(3)當數據元素增多時,set的拔出和搜刮速度變更若何?

假如你曉得log2的關系你應當就完全懂得這個謎底。在set中查找是應用二分查找,也就是說,假如有16個元素,最多須要比擬4次就可以找到成果,有32個元素,最多比擬5次。那末有10000個呢?最多比擬的次數為log10000,最多為14次,假如是20000個元素呢?最多不外15次。看見了吧,當數據量增年夜一倍的時刻,搜刮次數只不外多了1次,多了1/14的搜刮時光罷了。你明確這個事理後,便可以安心往外面放入元素了。

2.set中經常使用的辦法

--------------------------------------------------------------------------------

begin()        ,前往set容器的第一個元素

end()      ,前往set容器的最初一個元素

clear()          ,刪除set容器中的一切的元素

empty()    ,斷定set容器能否為空

max_size()   ,前往set容器能夠包括的元素最年夜個數

size()      ,前往以後set容器中的元素個數

rbegin     ,前往的值和end()雷同

rend()     ,前往的值和rbegin()雷同

寫一個法式練一練這幾個簡略操作吧:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(1);
    cout<<"set 的 size 值為 :"<<s.size()<<endl;
    cout<<"set 的 maxsize的值為 :"<<s.max_size()<<endl;
    cout<<"set 中的第一個元素是 :"<<*s.begin()<<endl;
    cout<<"set 中的最初一個元素是:"<<*s.end()<<endl;
    s.clear();
    if(s.empty())
    {
        cout<<"set 為空 !!!"<<endl;
    }
    cout<<"set 的 size 值為 :"<<s.size()<<endl;
    cout<<"set 的 maxsize的值為 :"<<s.max_size()<<endl;
    return 0;
}

運轉成果:

小結:拔出3以後固然拔出了一個1,然則我們發明set中最初一個值依然是3哈,這就是set 。還要留意begin() 和 end()函數是不檢討set能否為空的,應用前最好應用empty()磨練一下set能否為空.

--------------------------------------------------------------------------------

count() 用來查找set中某個某個鍵值湧現的次數。這個函數在set其實不是很適用,由於一個鍵值在set只能夠湧現0或1次,如許就釀成了斷定某一鍵值能否在set湧現過了。

示例代碼:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(1);
    cout<<"set 中 1 湧現的次數是 :"<<s.count(1)<<endl;
    cout<<"set 中 4 湧現的次數是 :"<<s.count(4)<<endl;
    return 0;
}

運轉成果:

equal_range() ,前往一對定位器,分離表現第一個年夜於或等於給定症結值的元素和 第一個年夜於給定症結值的元素,這個前往值是一個pair類型,假如這一對定位器中哪一個前往掉敗,就會等於end()的值。詳細這個有甚麼用處我還沒碰到過~~~

示例代碼:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> s;
    set<int>::iterator iter;
    for(int i = 1 ; i <= 5; ++i)
    {
        s.insert(i);
    }
    for(iter = s.begin() ; iter != s.end() ; ++iter)
    {
        cout<<*iter<<" ";
    }
    cout<<endl;
    pair<set<int>::const_iterator,set<int>::const_iterator> pr;
    pr = s.equal_range(3);
    cout<<"第一個年夜於等於 3 的數是 :"<<*pr.first<<endl;
    cout<<"第一個年夜於 3的數是 : "<<*pr.second<<endl;
    return 0;
}

運轉成果:

erase(iterator)  ,刪除定位器iterator指向的值

erase(first,second),刪除定位器first和second之間的值

erase(key_value),刪除鍵值key_value的值

看看法式吧:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> s;
    set<int>::const_iterator iter;
    set<int>::iterator first;
    set<int>::iterator second;
    for(int i = 1 ; i <= 10 ; ++i)
    {
        s.insert(i);
    }
    //第一種刪除
    s.erase(s.begin());
    //第二種刪除
    first = s.begin();
    second = s.begin();
    second++;
    second++;
    s.erase(first,second);
    //第三種刪除
    s.erase(8);
    cout<<"刪除後 set 中元素是 :";
    for(iter = s.begin() ; iter != s.end() ; ++iter)
    {
        cout<<*iter<<" ";
    }
    cout<<endl;
    return 0;
}

運轉成果:

小結:set中的刪除操作是不停止任何的毛病檢討的,好比定位器的能否正當等等,所以用的時刻本身必定要留意。

--------------------------------------------------------------------------------

find()  ,前往給定值值得定位器,假如沒找到則前往end()。

示例代碼:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    int a[] = {1,2,3};
    set<int> s(a,a+3);
    set<int>::iterator iter;
    if((iter = s.find(2)) != s.end())
    {
        cout<<*iter<<endl;
    }
    return 0;
}

insert(key_value); 將key_value拔出到set中 ,前往值是pair<set<int>::iterator,bool>,bool標記著拔出能否勝利,而iterator代表拔出的地位,若key_value曾經在set中,則iterator表現的key_value在set中的地位。

inset(first,second);將定位器first到second之間的元素拔出到set中,前往值是void.

示例代碼:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    int a[] = {1,2,3};
    set<int> s;
    set<int>::iterator iter;
    s.insert(a,a+3);
    for(iter = s.begin() ; iter != s.end() ; ++iter)
    {
        cout<<*iter<<" ";
    }
    cout<<endl;
    pair<set<int>::iterator,bool> pr;
    pr = s.insert(5);
    if(pr.second)
    {
        cout<<*pr.first<<endl;
    }
    return 0;
}

運轉成果:

lower_bound(key_value) ,前往第一個年夜於等於key_value的定位器

upper_bound(key_value),前往最初一個年夜於等於key_value的定位器

示例代碼:

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set<int> s;
    s.insert(1);
    s.insert(3);
    s.insert(4);
    cout<<*s.lower_bound(2)<<endl;
    cout<<*s.lower_bound(3)<<endl;
    cout<<*s.upper_bound(3)<<endl;
    return 0;
}

運轉成果:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved