1. 程式人生 > >STL學習筆記— —容器map和multimap

STL學習筆記— —容器map和multimap

簡介

在標頭檔案<map> 中定義

namespace std 
{
    template <typename Key, typename T,
            typename Compare = less<Key>,
            typename Allocator = allocator<pair<const Key,T> > >
        class map;
    template <typename Key, typename T,
            typename Compare = less<Key>,
            typename
Allocator = allocator<pair<const Key,T> > > class multimap; }

map和multimap都是有序關聯容器,包含具有唯一鍵的鍵值對。鍵使用比較函式Compare比較來進行排序。搜尋,刪除和插入操作具有對數複雜性。map和multimap通常實現為紅黑樹。multimap相對map來說能夠允許重複值的存在。

這裡寫圖片描述

這裡寫圖片描述

map和multimap操作

構造、複製與析構

map c //預設建構函式;建立一個空map/multimap

map c(op) //建立一個空map/multimap,並以op原則作為排序準則

map
c(c2) //複製建構函式;建立一個新的map/multimap作為c2的副本(所有元素都被複制) map c = c2 //複製建構函式;建立一個新的map作為c2的副本(所有元素都被複制) map c(rv) //移動建構函式;使用右值物件rv建立一個新map/multimap map c = rv //移動建構函式;使用右值物件rv建立一個新map/multimap map c(beg,end) //建立一個map/multimap,並使用beg到end範圍內的值進行初始化 map c(beg,end,op) //建立一個map/multimap,並使用beg到end範圍內以op原則排序後的值進行初始化 map
c(initlist) //建立一個map/multimap,並使用初始化列表進行初始化 map c = initlist //建立一個map/multimap,並使用初始化列表進行初始化 c.~map() //銷燬所有元素並釋放記憶體

在這裡map可能是如下的一種:

map<Key,Val> //以less<>為排序準則的map

map<Key,Val,Op> //以op為排序準則的map

multimap<Key,Val> //以less<>為排序準則的multimap

multimap<Key,Val,Op> //以op為排序準則的multimap

非變動性操作

c.key_comp() //返回比較準則

c.value_comp() //返回對值比較的標準 (與
key_comp()相同)

c.empty() //判斷容器是否為空,與size()==0相同,但可能更快

c.size() //返回當前元素數量

c.max_size() //返回可容納的元素最大數量

c1 == c2 //判斷c1與c2是否相等

c1 != c2 //判斷c1與c2是否不相等,等同於!(c1==c2)

c1 < c2 //判斷c1是否小於c2

c1 > c2 //判斷c1是否大於c2

c1 <= c2 //判斷c1是否小於等於c2

c1 >= c2 //判斷c1是否大於等於c2

特殊查詢操作

c.count(key) //返回鍵值為key的元素個數

c.find(key) //返回第一個鍵值為key的位置,若沒找到返回end()

c.lower_bound(key) //返回鍵值為key的第一個可插入的位置,也就是鍵值 >= key的第一個元素位置

c.upper_bound(key) //返回鍵值為key的最後一個可插入的位置,也就是鍵值 > key的第一個元素位置

c.equal_range(key) //返回鍵值為key的可插入的第一個位置和最後一個位置的區間,也就是鍵值 == key的元素區間

賦值

c = c2 //將c2所有元素賦值給c

c = rv //將右值物件rv的所有元素移動賦值給c

c = initlist //使用初始化列表進行賦值

c1.swap(c2) //交換c1和c2的數

swap(c1,c2) //交換c1和c2的數

迭代器相關函式

c.begin() //返回一個雙向迭代器,指向第一個元素

c.end() //返回一個雙向迭代器,指向最後一個元素

c.cbegin() //返回一個雙向常迭代器,指向第一個元素

c.cend() //返回一個雙向常迭代器,指向最後一個元素

c.rbegin() //返回一個逆向迭代器,指向逆向迭代的第一個元素

c.rend() //返回一個逆向迭代器,指向逆向迭代的最後一個元素

c.crbegin() //返回一個逆向常迭代器,指向逆向迭代的第一個元素

c.crend() //返回一個逆向常迭代器,指向逆向迭代的最後一個元素

插入和移除元素

c.insert(val) //插入一個val的副本,返回新元素位置(對map來說不論成功與否)

c.insert(pos,val) //插入一個val副本,返回新元素位置(pos應該是插入的搜尋起點)

c.insert(beg,end) //將範圍beg到end的所有元素的副本插入到c(無返回值)

c.insert(initlist) //插入初始化列表的所有元素的副本(無返回值)

c.emplace(args...) //插入一個使用args初始化的元素副本,返回新元素位置(對map來說不論成功與否)

c.emplace_hint(pos,args...) //插入一個使用args初始化的元素副本,返回新元素位置(pos應該是插入的搜尋起點)

c.erase(val) //移除所有與val值相等的元素,並返移除的元素個數

c.erase(pos) //移除迭代器位置的元素,並返回下個元素的位置

c.erase(beg,end) //移除beg到end範圍內的所有元素,並返回下個元素的位置

c.clear() //移除所以元素,清空容器

鍵值對轉遞

//使用value_type
std::map<std::string,float> coll;

coll.insert(std::map<std::string,float>::value_type("otto",22.3));

//使用pair<>
std::map<std::string,float> coll;

coll.insert(std::pair<std::string,float>("otto",22.3));

//使用make_pair()
std::map<std::string,float> coll;

coll.insert(std::make_pair("otto",22.3));

把map當作關聯陣列使用

c[key] //返回一個指向鍵值為key的元素的引用,如果不存在就插入這個元素

c.at(key) //返回一個指向鍵值為key的元素的引用

栗子1

//使用演算法和lambda

#include <map>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    map<string,double> coll { { "tim", 9.9 }, { "struppi", 11.77 } };

    //對每個元素的值平方
    for_each (coll.begin(), coll.end(),
              [] (pair<const string,double>& elem)
              {
                  elem.second *= elem.second;
                });

    //輸出元素
    for_each (coll.begin(), coll.end(),
              [] (const map<string,double>::value_type& elem)
              {
                  cout << elem.first << ": " << elem.second << endl;
                });

    return 0;
}

輸出1

struppi: 138.533
tim: 98.01

栗子2

//當作關聯陣列使用

#include <map>
#include <string>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    //建立map,鍵為string,值為float
    typedef map<string,float> StringFloatMap;
    StringFloatMap stocks;

    //插入元素
    stocks["BASF"] = 369.50;
    stocks["VW"] = 413.50;
    stocks["Daimler"] = 819.00;
    stocks["BMW"] = 834.00;
    stocks["Siemens"] = 842.20;

    //輸出元素
    StringFloatMap::iterator pos;
    cout << left; //左對齊
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        cout << "stock: " << setw(12) << pos->first
             << "price: " << pos->second << endl;
    }
    cout << endl;

    //所有price翻一番
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        pos->second *= 2;
    }

    //輸出元素
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        cout << "stock: " << setw(12) << pos->first
             << "price: " << pos->second << endl;
    }
    cout << endl;

    // 修改VM鍵為Volkswagen鍵
    stocks["Volkswagen"] = stocks["VW"];
    stocks.erase("VW");

    //輸出元素
    for (pos = stocks.begin(); pos != stocks.end(); ++pos)
    {
        cout << "stock: " << setw(12) << pos->first
             << "price: " << pos->second << endl;
    }

    return 0;
}

輸出2

stock: BASF price: 369.5
stock: BMW price: 834
stock: Daimler price: 819
stock: Siemens price: 842.2
stock: VW price: 413.5

stock: BASF price: 739
stock: BMW price: 1668
stock: Daimler price: 1638
stock: Siemens price: 1684.4
stock: VW price: 827

stock: BASF price: 739
stock: BMW price: 1668
stock: Daimler price: 1638
stock: Siemens price: 1684.4
stock: Volkswagen price: 827

栗子3

//作為字典使用

#include <map>
#include <string>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    //建立multimap作為字典
    multimap<string,string> dict;

    //插入元素
    dict.insert ( { {"day","Tag"}, {"strange","fremd"},
        {"car","Auto"}, {"smart","elegant"},
        {"trait","Merkmal"}, {"strange","seltsam"},
        {"smart","raffiniert"}, {"smart","klug"},
        {"clever","raffiniert"}
        } );

    //輸出元素
    cout.setf (ios::left, ios::adjustfield);
    cout << ' ' << setw(10) << "english "
         << "german " << endl;
    cout << setfill('-') << setw(20) << ""
         << setfill(' ') << endl;
    for ( const auto& elem : dict )
    {
        cout << ' ' << setw(10) << elem.first
             << elem.second << endl;
    }
    cout << endl;

    //輸出所有smart鍵的值
    string word("smart");
    cout << word << ": " << endl;
    for (auto pos = dict.lower_bound(word);
            pos != dict.upper_bound(word);
            ++pos)
    {
        cout << " " << pos->second << endl;
    }

    //輸出所以值為raffiniert的鍵
    word = ("raffiniert");
    cout << word << ": " << endl;
    for (const auto& elem : dict)
    {
        if (elem.second == word)
        {
            cout << " " << elem.first << endl;
        }
    }

    return 0;
}

輸出3

english german
--------------------
car Auto
clever raffiniert
day Tag
smart elegant
smart raffiniert
smart klug
strange fremd
strange seltsam
trait Merkmal

smart:
elegant
raffiniert
klug
raffiniert:
clever
smart

栗子4

//查詢

#include <map>
#include <iostream>
#include <algorithm>
#include <utility>
using namespace std;
int main()
{
    // 建立鍵與值都為float的map,並初始化
    map<float,float> coll = { {1,7}, {2,4}, {3,2}, {4,3},
        {5,6}, {6,1}, {7,3}
    };

    //查詢一個key為3的元素,對數時間複雜度
    auto posKey = coll.find(3.0);
    if (posKey != coll.end())
    {
        cout << "key 3.0 found ("
             << posKey->first << ":"
             << posKey->second << ")" << endl;
    }

    //查詢一個值為3的元素,線性時間複雜度
    auto posVal = find_if(coll.begin(),coll.end(),
                          [] (const pair<float,float>& elem)
    {
        return elem.second == 3.0;
    });

    if (posVal != coll.end())
    {
        cout << "value 3.0 found ("
             << posVal->first << ":"
             << posVal->second << ")" << endl;
    }

    return 0;
}

輸出4

key 3.0 found (3:2)
value 3.0 found (4:3)

栗子5

//結合string,執行時排序

#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>

using namespace std;

//字串比較函式,允許在執行事設定比較準則,允許在不分大小寫的情況下比較
class RuntimeStringCmp
{
public:

    //比較標準常數
    enum cmp_mode {normal, nocase};
private:

    //實際比較模式
    const cmp_mode mode;

    //輔助函式,大小轉化一致
    static bool nocase_compare (char c1, char c2)
    {
        return toupper(c1) < toupper(c2);
    }
public:

    //建構函式: 初始化比較準則
    RuntimeStringCmp (cmp_mode m=normal) : mode(m)
    {
    }

    //比較
    bool operator() (const string& s1, const string& s2) const
    {
        if (mode == normal)
        {
            return s1<s2;
        }
        else
        {
            return lexicographical_compare (s1.begin(), s1.end(),
                                            s2.begin(), s2.end(),
                                            nocase_compare);
        }
    }
};

typedef map<string,string,RuntimeStringCmp> StringStringMap;

//填充和輸出函式
void fillAndPrint(StringStringMap& coll);

int main()
{
    //以預設比較準則建立容器
    StringStringMap coll1;
    fillAndPrint(coll1);

    //建立一個不區分大小寫的比較物件
    RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);

    //建立一個不區分大小寫的比較準則容器
    StringStringMap coll2(ignorecase);
    fillAndPrint(coll2);

    return 0;
}
void fillAndPrint(StringStringMap& coll)
{
    //插入元素
    coll["Deutschland"] = "Germany";
    coll["deutsch"] = "German";
    coll["Haken"] = "snag";
    coll["arbeiten"] = "work";
    coll["Hund"] = "dog";
    coll["gehen"] = "go";
    coll["Unternehmen"] = "enterprise";
    coll["unternehmen"] = "undertake";
    coll["gehen"] = "walk";
    coll["Bestatter"] = "undertaker";

    //輸出元素
    cout.setf(ios::left, ios::adjustfield);
    for (const auto& elem : coll)
    {
        cout << setw(15) << elem.first << " "
             << elem.second << endl;
    }
    cout << endl;
}

輸出5

Bestatter undertaker
Deutschland Germany
Haken snag
Hund dog
Unternehmen enterprise
arbeiten work
deutsch German
gehen walk
unternehmen undertake

arbeiten work
Bestatter undertaker
deutsch German
Deutschland Germany
gehen walk
Haken snag
Hund dog
Unternehmen undertake