1. 程式人生 > >c++的關聯容器入門(map and set)

c++的關聯容器入門(map and set)

C++的關聯容器主要是兩大類map和set

我們知道談到C++容器時,我們會說到 順序容器(Sequence containers),關聯容器(Associative containers),無序關聯容器(Unordered associative containers)以及容器介面卡(Container adaptors),

另外,我相信,這些抽象的容器概念,應該是所有高階語言都有的。本文重點闡述關聯容器。

Associative containers implement sorted data structures that can be quickly searched (O(log n) complexity).

關聯容器實現了可以快速搜尋(O(log n)複雜度)的排序資料結構。

主要就是 set、map、multiset和multimap。

std::map

map is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare. Search, removal, and insertion operations have logarithmic complexity. Maps are usually implemented as red-black trees。

map是一個排序的關聯容器,它包含具有惟一鍵的鍵值對。通過使用Compare函式對鍵進行排序。搜尋、刪除和插入操作具有對數複雜度。對映通常被實現為紅黑樹

理解map需要理解鍵值對有序鍵值唯一以及對數級別的操作。

  • 鍵值對

    既然是關聯容器,那自然要關聯下,這裡的關聯就是key和value的關聯,通過std::map<string,string> mapStr;這樣,我們就定義了一個key為string ,value為string的map。我們可以通過中括號直接給鍵值對賦值:

    mapStr["name"] = "lckfa";
    mapStr["sexuality"] = "male";

    事實上,map的底層是使用pair來實現的,std::pair是一個結構模板,它提供了一種將兩個異構物件儲存為單個單元的方法。因此還可以使用如下程式碼完成上面的操作:

    pair<string,string> pair1("name","lckfa");
    pair<string,string> pair2("sexuality","male");
    mapStr.insert(pair1);
    mapStr.insert(pair2);
  • 有序

    為了看看map是怎麼有序的,我們先弄個列印函數出來

    template<typename Map>
    void print_map(Map& m){
        std::cout << "{ " ;
        for_each(m.begin(),m.end(),[&](Map::value_type& p){
            std::cout << p.first <<":"<<p.second<<' ';
        });
        std::cout << "}" ;
    }

    這個列印函式模板,可以列印任何型別的map。這下再也不擔心map的型別改變了。還不會使用labmda表示式的,可以去看我的另一篇博文,另外value_type可以理解為pair,這裡和Map是一個型別。

    然後,我們在之前的map裡新增一個鍵值對

    mapStr["sss"] = "sss";
    mapStr["aaa"] = "aaa";
    mapStr["bbv"] = "bbb";

    使用pair,然後insert也行。

    然後呼叫print_map函式,結果如下:

    { aaa:aaa bbv:bbb name:lckfa sexuality:male sss:sss }

    以上結果充分說明 map是按key的升序排列的。

    備註,如果你想自定義map的排序方式,可以參考這裡

  • 鍵值唯一

    白話就是,這裡的key值總是唯一的,那麼讓我們來驗證下,同時向map裡插入相同鍵值會發生什麼:

    mapStr["name"] = "lckfa";
    mapStr["sexuality"] = "male";
    mapStr["name"] = "mal9";

    列印結果:

    { name:mal9 sexuality:male }

    從結果可知,再重新設定某個key的value後,後一個會覆蓋前一個value。

  • 對數級別的複雜度操作

    這個就不展開了,有興趣的可以瞭解一個紅黑樹

std::set

std::set is an associative container that contains a sorted set of unique objects of type Key. Sorting is done using the key comparison function Compare. Search, removal, and insertion operations have logarithmic complexity. Sets are usually implemented as red-black trees

set是一個關聯容器,它包含一組型別為Key的已排序的惟一物件。排序是使用key的比較函式比較來完成的。搜尋、刪除和插入操作具有對數複雜度。集合通常被實現為紅黑樹。

和map一樣,除了map的鍵值對差異,set只有key,這樣的差異外,set和map再定義和使用上沒有很大的差異。同樣的set也具有 key唯一,有序,對數複雜度的特點,這裡使用一個統一的程式碼說明下:

template<typename Set>
void print_set(Set& s){
    cout << "{ ";
    for_each(s.begin(),s.end(),[&](Set::key_type k){
        std::cout << k <<' ';
    });
    std::cout << "}" ;
}

std::set<int> setInt;
setInt.insert(4);
setInt.insert(2);
setInt.insert(5);
setInt.insert(2);

std::set<string> setStr;
setStr.insert("hello");
setStr.insert("set");
setStr.insert("world");
setStr.insert("set");
print_set(setInt);
print_set(setStr);

測試輸出結果:

{ 2 4 5 }{ hello set world }

由結果可知:set的key值也是唯一的,同時按升序排列,如果希望自定義排列,需要需改比較函式。

小結:本文初略的整理了map和set的基礎使用,說明了二者的特性,key唯一,有序,演算法對數級。僅僅能作為初學者參考。