c++ map/multimap,set/multiset的用法及比較

一,相關介紹
map/multimap,set/multiset都爲c++中的標準容器,它們的底層都是用紅黑樹實現的,因此在進行查詢,修改,刪除等操作上具有很高的效率,可以達到O(logN)。
那麼它們的區別是什麼呢?
1,其中map/multimap是kay-value結構,意思爲它存儲的是一對數據,其中kay爲關鍵字信息,而value爲相應的鍵值;而set/multiset爲kay結構,它沒有相應的value信息。
2,由於map/set是用紅黑樹實現的,所以它不允許kay值相同的數據插入(在後面的例子中我們將展現這種特性);爲了應對相應的需求,於是便有了multimap和multiset,它們允許kay值相同的數據插入。
二,具體使用
注意:在使用前需要包相應的頭文件。
1,map的使用

#pragma once
#include<map>
#include<set>
#include<string>
#include<iostream>
using namespace std;
//map與set都是c++裏面的標準容器,它們底層的實現都是通過紅黑樹完成的,而map與set的區別在與map爲kay-value結構,而set爲key結構
//由於是紅黑樹,所以它裏面不允許有相同kay值存在,所以若重複插入,結果不變。
void myTest()
{
    map<string, string> myMap;
    myMap.insert("left", "左邊");
    myMap.insert("right", "右邊");
    map<string, string>::iterator it = myMap.begin();
    for (; it != myMap.end(); it++)
    {
        cout << (*it)<<endl;
    }
}

上面爲自定義的一個map(爲string-string類型),然後向裏面插入了兩個值(map爲kay-value結構);
緊接着我們又定義了一個迭代器it,其中begin()方法是用來獲取map中的第一個數據,end( )則用來獲得最後一個數據。
細心的朋友會發現,這份代碼並不能跑起來(直接編譯不通過),並且提示insert那裏有問題,其實這是因爲,在STL中,爲了方便迭代器的實現(感興趣的同學可以去查看相應的資料),在map中的insert並不是直接插入數據的,它插入的是一個pair的對象;pair是一個結構體,它如下結構

template<class k,class v>
struct pair{
      k _first;
      v _second

}

在c++裏面已經定義好了該結構,它的make_pair(k,v)方法便是用來生成pair類型的變量的,搞清楚了這個問題,我們再修改代碼

#pragma once
#include<map>
#include<set>
#include<string>
#include<iostream>
using namespace std;
//map與set都是c++裏面的標準容器,它們底層的實現都是通過紅黑樹完成的,而map與set的區別在與map爲kay-value結構,而set爲key結構
//由於是紅黑樹,所以它裏面不允許有相同kay值存在,所以若重複插入,結果不變。
void myTest()
{
    map<string, string> myMap;
    myMap.insert(make_pair("right", "右邊"));
    myMap.insert(make_pair("hello", "你好"));
    myMap.insert(make_pair("where", "哪裏"));
    //myMap["1112"] = "無語de today";

    map<string, string>::iterator it = myMap.begin();
    for (; it != myMap.end(); it++)
    {
        cout << (*it).first<<"  "<<(*it).second<<endl;
    }
}

運行結果:
這裏寫圖片描述
現在便能正常把代碼跑起來了。
另外其中的it是迭代器,begin()方法用來返回map中的第一個數據,而end方法用來返回map中最後一個數據,此處我們用來遍歷myMap;正如前面所講的一樣,由於map中插入的是一個pair對象,而*it便是pair對象,所以我們可以調用它的first及second方法間接的完成對kay-value的訪問
那麼數據該怎麼刪除呢?
(1)
iterator erase (const_iterator position);
(2)
size_type erase (const key_type& k);
(3)
iterator erase (const_iterator first, const_iterator last);
以上是map提供的對數據的刪除方法,我們可以看到可以通過erase刪除一個迭代器所指向的節點
也可以刪除指定的k,甚至可以刪除一個迭代器區間,此處便不再演示。
對數據的查找:find()方法
首先先看函數的原型:
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
它的返回值是iterator,即一個迭代器;其中const_iterator返回的爲const迭代器,它所指向的pair所指向的值是不可以被修改的;接下來我們來測試一下普通迭代器的find()方法:

#pragma once
#include<map>
#include<string>
#include<iostream>
using namespace std;
//map與set都是c++裏面的標準容器,它們底層的實現都是通過紅黑樹完成的,而map與set的區別在與map爲kay-value結構,而set爲key結構
//由於是紅黑樹,所以它裏面不允許有相同kay值存在,所以若重複插入,結果不變。
void myTest()
{
    map<string, string> myMap;
    myMap.insert(make_pair("right", "右邊"));
    myMap.insert(make_pair("hello", "你好"));
    myMap.insert(make_pair("where", "哪裏"));
    cout << myMap.find("right")->second << endl;
    cout << myMap.find("hello")->second << endl;
    cout << myMap.find("where")->second << endl;

}

運行結果:
這裏寫圖片描述
從結果我們可以看到,通過相應的key值便能找到對應的value,但是需要注意的是如果查找一個不存在的將會產生一箇中斷,另外若想通過value查找key也會出錯。爲了避免沒有查到相應的key
值而出錯,我們可以選擇一個迭代器指向自定義map的最後,如果通過find()返回的迭代器與其end相同就代表沒有找到,並輸出相應的信息。修改後的主要代碼如下:

map<string, string>::iterator it;
    map<string, string>::iterator flag=myMap.end();
    it = myMap.find("wuyu");
    if (it != flag)
    {
        cout << (*it).second << endl;
    }
    else
    {
        cout << "沒有找到" << endl;
    }

此時查找key值爲:“wuyu”
運行結果:
這裏寫圖片描述

map數據的修改
請看代碼:
方式1:

map<string, string> myMap;
    myMap.insert(make_pair("right", "右邊"));
    myMap.insert(make_pair("hello", "你好"));
    myMap.insert(make_pair("where", "哪裏"));
    myMap.insert(make_pair("left", "左邊"));
    map<string, string>::iterator it;
    map<string, string>::iterator flag=myMap.end();
    it = myMap.find("left");
    if (it != flag)
    {
        (*it).second = "剩餘";
    }
    else
    {
        cout << "沒有找到" << endl;
    }
    for (it = myMap.begin(); it != myMap.end(); it++)
    {
        cout << (*it).first << "  " << (*it).second << endl;
    }
    cout << endl;

方式2:

#pragma once
#include<map>
#include<string>
#include<iostream>
using namespace std;
//map與set都是c++裏面的標準容器,它們底層的實現都是通過紅黑樹完成的,而map與set的區別在與map爲kay-value結構,而set爲key結構
//由於是紅黑樹,所以它裏面不允許有相同kay值存在,所以若重複插入,結果不變。
void myTest()
{
    map<string, string> myMap;
    myMap.insert(make_pair("right", "右邊"));
    myMap.insert(make_pair("hello", "你好"));
    myMap.insert(make_pair("where", "哪裏"));
    myMap.insert(make_pair("left", "左邊"));
    map<string, string>::iterator it;
    map<string, string>::iterator flag=myMap.end();
    it = myMap.find("left");
    if (it != flag)
    {
        (*it).second = "剩餘";
    }
    else
    {
        cout << "沒有找到" << endl;
    }
    for (it = myMap.begin(); it != myMap.end(); it++)
    {
        cout << (*it).first << "  " << (*it).second << endl;
    }
    cout << endl;
    //通過[]實現

    myMap["where"] = "在哪裏";
    myMap["left"] = "左邊";
    for (it = myMap.begin(); it != myMap.end(); it++)
    {
        cout << (*it).first << "  " << (*it).second << endl;
    }
    cout << endl;
}

運行結果:
這裏寫圖片描述
我們可以使用find()方法先找到指定的節點,再對其指向的key->value直接進行修改,但這種方法較爲麻煩;我們比較常用的是直接調“【】”運算符,由於在定義iterator時對它進行了重載,所以可以直接訪問相應的數據並對其進行修改。

發佈了34 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章