日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

set和multiset容器

發布時間:2025/4/16 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 set和multiset容器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 set和multiset容器的能力
set 和multiset容器的內部結構通常由平衡二叉樹(balancedbinary tree)來實現。當元素放入容器中時,會按照一定的排序法則自動排序,默認是按照less<>排序規則來排序。這種自動排序的特性加速了元素查找的過程,但是也帶來了一個問題:不可以直接修改set或multiset容器中的元素值,因為這樣做就可能違反了元素自動排序的規則。如果你希望修改一個元素的值,必須先刪除原有的元素,再插入新的元素。

2 set和multiset容器的操作
Constructor and Destructor

[cpp]?view plaincopy
  • set?c:創建一個空的set或multiset容器??
  • set?c(op):創建一個空的使用op作為排序法則的set或multiset容器??
  • set?c1(c2):創建一個已存在的set或multiset容器的復制品,容器的類型和所有元素一同復制??
  • set?c(beg,?end):創建一個set或multiset容器,并且以[beg,?end)范圍中的元素進行初始化??
  • set?c(beg,?end,?op):創建一個使用op作為排序法則的set或multiset容器,并且以[beg,?end)范圍中的元素進行初始化??
  • c.~set():容器的析構函數,銷毀所有的元素,釋放所有的分配內存??
  • 上面的set可以是下面幾種形式:

    [cpp]?view plaincopy
  • set<type>:以less<>為排序法則的set??
  • set<type,?op>:以op為排序法則的set??
  • multiset<type>:以less<>為排序法則的multiset??
  • multiset<type,?op>:以op為排序法則的multiset??
  • 從上面我們可以看到,可以從兩個地方來指定排序法則:

    (1)作為模板參數

    例如:std::set<int, greater<int> > col1;

    這種情況下,排序法則本身作為容器類型的一部分。對于一個set或者multiset容器,只有當元素類型和排序法則類型都相同時,他們的類型才被認為相同,否則就是不同類型的容器。

    (2)作為構造函數參數
    例如:std::set<int> col1(greater<int>);

    這種情況下指定的排序法則不作為容器類型的一部分,你可以為相同類型的容器指定不同的排序規則。這通常應用于要求相同的容器類型,但排序規則可以不同的場合。

    Size and Comparing
    set?
    和multiset容器同樣提供size(), empty(), max_size()三個關于查詢元素數目的接口,提供==,!=, <, <=, >, >=等比較操作符。但值得注意的是比較操作符只針對相同類型的容器,元素類型和排序法則類型都必須相同。

    Special Search Operations
    set和multiset容器的內部結構對于元素的查找提供了優化空間,所以它們提供了一些特殊的查找接口,這些查找操作通常要比同名的通用算法高效,所以在相同的條件下應該優先使用這些接口。

    [cpp]?view plaincopy
  • count(val):?返回容器中值等于val的元素數目。??
  • find(val):?返回容器中值等于val的第一個元素的iterator位置;如果沒有匹配元素,則返回end()位置。??
  • lower_bound(val):?返回容器中第一個值大于或等于val的元素的iterator位置。??
  • upper_bound(val):?返回容器中第一個值大于val的元素的iterator位置。??
  • equal_range(val):?返回容器中值等于val的所有元素的范圍[beg,?end)組成的pair<beg,?end>?。??
  • 下面我們看一個使用lower_bound(), upper_bound和equal_range(val)例子,以加深對它們的理解:

    [cpp]?view plaincopy
  • #include?<iostream>??
  • #include?<set>??
  • #include?"print.hpp"??
  • using?namespace?std;??
  • int?main()??
  • {??
  • ????multiset<int>?col1;??
  • ???
  • ????col1.insert(2);??
  • ????col1.insert(5);??
  • ????col1.insert(4);??
  • ????col1.insert(6);??
  • ????col1.insert(1);??
  • ????col1.insert(5);??
  • ???
  • ????PRINT_ELEMENTS(col1,?"col1:");??
  • ????cout?<<?endl;??
  • ???
  • ????multiset<int>::const_iteratorpos;??
  • ????pair<multiset<int>::iterator,multiset<int>::iterator>?range;??
  • ???
  • ????cout?<<?"lower_bound(3):"?<<?*col1.lower_bound(3)?<<?endl;??
  • ????cout?<<?"upper_bound(3):"?<<?*col1.upper_bound(3)?<<?endl;??
  • ????range?=?col1.equal_range(3);??
  • ????cout?<<?"equal_range(3):"?<<?*range.first?<<?"?"?<<?*range.second<<?endl;??
  • ????cout?<<?"elements?withvalue(3):?";??
  • ????for?(pos?=?range.first;?pos?!=range.second;?++pos)??
  • ????{??
  • ????????cout?<<?*pos<<?"?";??
  • ????}??
  • ????cout?<<?endl;??
  • ????cout?<<?endl;??
  • ???
  • ????cout?<<?"lower_bound(5):"?<<?*col1.lower_bound(5)?<<?endl;??
  • ????cout?<<?"upper_bound(5):"?<<?*col1.upper_bound(5)?<<?endl;??
  • ????range?=?col1.equal_range(5);??
  • ????cout?<<?"equal_range(5):"?<<?*range.first?<<?"?"?<<?*range.second<<?endl;??
  • ????cout?<<?"elements?withvalue(5):?";??
  • ????for?(pos?=?range.first;?pos?!=range.second;?++pos)??
  • ????{??
  • ????????cout?<<?*pos<<?"?";??
  • ????}??
  • ????cout?<<?endl;??
  • }??
  • 執行結果如下:??
  • col1:?1?2?4?5?5?6???
  • ???
  • lower_bound(3):?4??
  • upper_bound(3):?4??
  • equal_range(3):?4?4??
  • elements?with?value(3):???
  • ???
  • lower_bound(5):?5??
  • upper_bound(5):?6??
  • equal_range(5):?5?6??
  • elements?with?value(5):?5?5???
  • Assignment
    set
    和multiset容器只提供最基本的賦值操作:

    [cpp]?view plaincopy
  • c1?=?c2:?把c2的所有元素復制到c1中,同時c1原有的元素被銷毀。??
  • c1.swap(c2):?交換c1和c2的元素。??
  • swap(c1,?c2):?同上,只不過這是一個通用算法。??
  • 需要注意的是兩個容器的類型要一致(包括元素類型和排序法則類型)。

    Inserting and Removing Elements
    set
    和multiset容器的插入和刪除元素接口跟其他容器也非常類似,但在細節上卻存在差別。

    [cpp]?view plaincopy
  • c.insert(elem):?在容器中插入元素elem的一份拷貝,并返回新元素的iterator位置;如果是set容器,同時還返回是否插入成功的標志。??
  • c.insert(pos,?elem):?在容器中插入元素elem的一份拷貝,并返回新元素的iterator位置;因為set和multiset容器的元素是自動排序的,所以pos位置只是插入位置的一??????????????????????????個提?示,設置恰當的話,可以提高插入元素的效率。??
  • c.insert(beg,?end):?在容器中插入[beg,?end)范圍中所有元素的拷貝,沒有返回值。??
  • c.erase(val):?刪除容器中所有值為val的元素,返回刪除元素的數目。??
  • c.erase(pos):?刪除容器中位置pos處的元素,沒有返回值。??
  • c.erase(beg,?end):?刪除容器中[ben,?end)范圍內所有的元素,沒有返回值。??
  • c.clear():?刪除容器中所有元素,使容器成為空容器。??
  • 其中我們重點說一下c.insert(elem)接口。

    對于set容器,它的定義如下:

    pair<iterator, bool> insert(const TYPE& val);

    而對于multiset容器,它的定義如下:

    iterator insert(const TYPE& val);

    它 們的不同就是set容器的insert接口返回的是一個pair<iterator,bool>,而multiset容器的insert接口直接返回一個iterator。這是因為set容器中不允許有重復的元素,如果容器中已經存在一個跟插入值相同的元素,那么插入操作就會失敗,而pair中的bool值就是標識插入是否成功的。而multiset不存在這個問題。

    3 set和multiset容器的異常處理

    因為set和multiset容器的獨特內部結構,當發生異常時,也可以把影響減到最小。也就是說,跟list容器一樣,set和multiset容器的操作要么成功,要么對原有容器沒有影響。

    4?運行時指定排序法則

    通常情況下,我們是在定義容器時指定排序法則,就像下面形式:

    std::set<int, greater<int> > col1;

    或者

    std::set<int> col1;?? ?//use defaultsorting criterion less<>

    ?

    然而,如果你需要在運行時動態指定容器的排序法則,或者你希望對于相同的容器類型卻有著不同的排序法則,那么就要做一些特殊處理。下面我們看一個例子:

    [cpp]?view plaincopy
  • #include?<iostream>??
  • #include?<set>??
  • #include?"print.hpp"??
  • using?namespace?std;??
  • ???
  • template?<typename?T>??
  • class?RuntimeCmp???
  • {??
  • ????public:??
  • ????????enum?cmp_mode?{normal,reverse};??
  • ????private:??
  • ????????cmp_mode?mode;??
  • ????public:??
  • ????????RuntimeCmp(cmp_mode?m?=normal)?:?mode(m)?{}??
  • ???
  • ????????bool?operator()?(constT&?t1,?const?T&?t2)??
  • ????????{??
  • ????????????returnmode?==?normal???t1?<?t2?:?t1?>?t2;??
  • ????????}??
  • ???
  • ????????bool?operator==?(constT&?rhv)???
  • ????????{??
  • ????????????returnmode?==?rhv.mode;??
  • ????????}??
  • };??
  • ???
  • typedef?set<int,?RuntimeCmp<int>?>?IntSet;??
  • ???
  • //pre-declare??
  • void?fill(IntSet&?col1);??
  • ???
  • int?main()??
  • {??
  • ????IntSet?col1;??
  • ????fill(col1);??
  • ????PRINT_ELEMENTS(col1,?"col1:");??
  • ???
  • ????RuntimeCmp<int>reverse_cmp(RuntimeCmp<int>::reverse);??
  • ????IntSet?col2(reverse_cmp);??
  • ????fill(col2);??
  • ????PRINT_ELEMENTS(col2,?"col2:");??
  • ???
  • ????if?(col1?==?col2)???
  • ????{??
  • ????????cout?<<?"col1and?col2?is?equal"?<<endl;??
  • ????}??
  • ????else??
  • ????{??
  • ????????if?(col1?<col2)???
  • ????????{??
  • ????????????cout<<?"col1?is?less?than?col2"?<<?endl;??
  • ????????}??
  • ????????else???
  • ????????{??
  • ????????????cout<<?"col1?is?greater?than?col2"?<<?endl;??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??
  • ???
  • void?fill(IntSet&?col1)???
  • {??
  • ????col1.insert(2);??
  • ????col1.insert(3);??
  • ????col1.insert(6);??
  • ????col1.insert(5);??
  • ????col1.insert(1);??
  • ????col1.insert(4);??
  • }??
  • 運行結果如下:??
  • col1?1?2?3?4?5?6???
  • col2?6?5?4?3?2?1???
  • col1?is?less?than?col2??
  • 這里例子中,col1和col2有著相同的類型:set<int,RuntimeCmp<int> >,但是它們的排序法則卻不相同,一個升序,一個降序。這都是通過自定義的函數對象來實現的,所以函數對象比普通函數有著更加靈活與強大的控制,可以滿足一些特殊的需求。

    總結

    以上是生活随笔為你收集整理的set和multiset容器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。