一,相關介紹
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時對它進行了重載,所以可以直接訪問相應的數據並對其進行修改。