本文中,簡單總結一下使用unordered map 的心得。unordered_map容器屬于STL中關聯表的一種,常用的map容器與unordered_map容器在使用中有著很大程度的相同點,在之后的文章中我可能會針對二者的相同點與不同點進行細致的分析,這里就不過多贅述,只是簡單地和大家一起了解一下unordered_map的一些基本使用。
關聯表作為STL庫中的一類常見的容器,其結構和數組類似。與數組不同的是,關聯表中有兩個類型,鍵key索引類和被索引的元素類。Key值和元素的關系我們可以理解為映射關系。一個鍵值有且僅有一個對應的元素。
同時,關聯表中使用的索引類,不再是簡單的自然數,而是可以根據需要選擇使用string字符串類,或自定義的類作為索引key的類型。不再使用自然數作為索引讓關聯表的使用相較于數組更加靈活,但需要注意的是,一個關聯表中的所有鍵都應該是同一類型,所有被索引的元素也應該是同一類型。這兩個類型在定義關聯表的同時進行定義。下面我們就回到關聯表中的一種容器,本篇文章的主角 : unordered_map的使用。
0.include相關庫。
# include <unordered_map>
1.定義一個一維的unordered map:
第一部分,如何定義一個空的unordered_map容器。
unordered_map<uint64_t,string> mymap;
unordered_map<uint64_t,uint64_t> mymap2a
unordered_map<string,string>mymap3;
<>中的第一個參數是key的類型,第二個參數是對應的元素集的數據類型。unordered_map類可以理解為一個使用key作為角標標注的列表,只不過這個列表是無序的,且列表的序號也不再要求一定是正整數。與數組比較,unordered map等容器更加自由,更易于查找。
2.向unordered_map里添加項:
這個部分我們介紹一些向unordered_map里添加項的方法。
// 1. 使用insert方法
mymap.insert(make_pair(10,"nihao"));
mymap.insert(pair<uint64_t,string>(20,"hello"));
uint64_t ind = 30;
string toto = "hello";
mymap.insert(pair<uint64_t,string>(ind,toto));
//2. 使用角標直接賦值
mymap[40] = "nihaoma";
需要注意的是,一個key只能對應一個存儲的數據。如果key已經存在了,使用insert方法對已存在的key進行插入操作不會覆蓋之前key對應的值,而使用中括號,類似數組的賦值方法,例如mymap[10]="hahaha"可以覆蓋已存在的key所對應的值。當然,如果使用中括號賦值時中括號中的key值在容器中不存在,那么此時中括號賦值的效果和使用insert方法一致,會為容器添加一個新的key 鍵,并插入對應的值。這一點在接下來我們使用二維unordered_map時還會進一步說明。
3.迭代器 iterator
由于unordered_map其中的項是沒有順序排列的,且鍵值可以不為正整數,因此為了對unordered_map中的每一項進行操作,且和數組一樣滿足我們遍歷的需要,就必須使用迭代器。
迭代器的定義方法很簡單,C<>::iterator name_iterator;
延續上述例子, 迭代器的定義方法代碼如下:
unordered_map<uint64_t,string>::iterator ite_mymap;
迭代器可以使用容器的begin()或end()方法進行初始化 :
unordered_map<uint64_t,string>::iterator ite_mymap(mymap.begin());
迭代器可以理解為指向容器某一項的指針,每一項都包含一個key值和一個元素值,和指針一樣,用*ite_mymap可以對迭代器取值。下述代碼是一個簡單的使用迭代器讀取key值和元素值的例子:
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{unordered_map < uint64_t, uint64_t > mymap;mymap.insert(make_pair(10, 20));unordered_map < uint64_t, uint64_t >::iterator ite_mymap(mymap.begin());cout << (*ite_mymap).first<<endl;cout << (*ite_mymap).second << endl;cout << ite_mymap->first << endl;cout << ite_mymap->second << endl;return 0;
}
執行結果如下 :
通過上述代碼以及執行結果我們不難看出,容器中的每一項,都包含有first和second兩個屬性,分別對應了key 鍵值和元素值。我們既可以通過指向項的迭代器指針讀取這兩個屬性,同時也可以使用取值符號,直接通過項來讀取這兩個屬性。
4. 使用迭代器遍歷
有了在上述步驟中的認識,使用迭代器遍歷容器也變得非常簡單,使用一個for循環就可以遍歷容器并利用迭代器進行操作了 :
for(ite_mymap=mymap.begin();ite_mymap!=mymap.end();ite_mymap++)
{...
}
5.二維unordered_map的使用
通過上面的幾個部分,我們已經大致了解了一維unordered_map的使用。正如一開始我們提到的,unordered_map中被索引的元素類型可以是任意類,二維unordered_map實際就是被索引的元素集是令一個unordered_map類,這樣就構成了二維的unordered_map。下面是一個簡單的例子:
unordered_map<uint64_t, unordered_map<uint64_t, uint64_t>> mymap;
unordered_map<uint64_t, uint64_t> tmp;
tmp.insert(make_pair(10, 25));
mymap.insert(pair < uint64_t, unordered_map<uint64_t, uint64_t>>(10, tmp));
mymap[10][20] = 30;
mymap[10][40] = 35;
mymap[20][40] = 50;
unordered_map<uint64_t, unordered_map<uint64_t, uint64_t>>::iterator multitr;
unordered_map<uint64_t, uint64_t>::iterator intertr;
for(multitr=mymap.begin();multitr!=mymap.end();multitr++){for(intertr= multitr ->second.begin(); intertr != multitr ->second.end(); intertr ++)std::cout<< multitr ->first<<" "<<intertr->first<<" ("<< intertr -> second <<")"<<endl;}
輸出結果如下 :
上述例子中,我們定義了unordered_map mymap,其鍵key類型為uint64_t,對應的元素類型為另一個unordered_map類。對于mymap來說,一個鍵對應一個unordered_map類的元素。對于二維unordered_map的遍歷,我們定義兩個迭代器,一個外部迭代器,一個內部迭代器。類似二維數組的遍歷,我們使用for循環的嵌套來遍歷二維的unordered_map。