1.map簡介
map中的元素是關鍵字-值對:關鍵字起到索引的作用,值表示與索引相關的數據。我們常用的字典就是很好的map的實例,單詞作為索引,其中文含義代表其值。map類型通常被稱為關聯數組,其和數組很相似,只不過其下標不是整數而是關鍵
字,我們通過關鍵字來查找值而不是位置。比如電話簿也是一個map的例子,姓名作為關鍵字其對應的值就為該人的電話號碼。map類型定義在頭文件map中。
注意:map是有序的且不允許重復關鍵字的關聯容器!其有序的實現是依靠關鍵字類型中的"<"來實現的。
2.map的定義與初始化
2.1 創建空map
map<key_type,value_type> tempMap;//創建空map
2.2 列表初始化map
map<key_type,value_type> tempMap{
{key1,value1},
{key2,value2},
......};
2.3 使用已有的map復制構造
map<key_type,value_type> tempMap(existMap);//注意關鍵字類型與值類型匹配
2.4 指定已有map的迭代器返回進行構造
map<key_type,value_type> tempMap(b,e);//b,e為已有map對象的迭代器范圍
3.map的賦值操作
我們可以將一個已有的map賦值給另一個map:
map1=map2;
map也支持列表賦值:
map<key_type,value_type> tempMap={ {key1,value1}, {key2,value2}, ......};
4.關聯容器額外的類型別名
除了之前的容器操作具有的類型,map有自己獨特的類型別名:
類型別名 | 說明 |
key_type |
關鍵字類型 |
mapped_type |
關鍵字關聯的類型 |
value_type |
pair<const key_type,mapped_type> |
舉例
map<int ,string> myMap; myMap::value_type v1;//v1為pair<const int ,string>類型
myMap::key_type v2;//v2為int類型
myMap::mapped_type v3;//v3為string類型
5. 新的數據類型 pair類型
pair標准類型定義在頭文件utility中,一個pair保存兩個數據成員,pair是用來生成特定類型的模板,當創建一個pair對象時必須要提供兩個類型名,
pair<string string> A;//保存兩個string
pair<string ,size_t> B;//保存一個string,一個size_t
pair<int ,vector<int>> C;//保存一個int和vector<int>
上面的代碼都是執行了默認構造函數來對數據成員進行初始化,我們也可以初始化器:
pair<string,string> thePair{"Hello","World"};
pair的數據成員是public的,並且成員命名為first和second,我們可以使用普通的成員訪問符“.”來進行訪問。
我們可以在pair上的操作如下:
操作 | 說明 |
pair<T1,T2> P; |
p的成員數據類型分別為T1,T2,並執行默認初始化 |
pair<T1,T2> p(v1,v2); |
P的成員數據類型分別為T1,T2,並且使用v1,v2分別初始化 |
pair<T1,T2> p={v1,v2}; |
等價於上式 |
make_pair(v1,v2); |
返回一個v1和v2初始化的pair,其類型由v1和v2推斷而來 |
p.first |
返回p的first成員 |
p.second |
返回p的second成員 |
p1 relop p2 |
執行關系運算(>,<,<=,>=),利用數據類型中的關系運算 |
p1==p2 |
相等性判斷,必須first和second同時滿足要求 |
p1!=p2 |
不等於判斷 |
5.1 創建使用pair對象的函數
pair<int ,string> do_something(vecotr<string> &v) { if(!v.empty()) { return {v.back().size(),v.back()}; } else { return pair<int ,string>(); } }
有些較早版本的編譯器不支持花括號返回,那我們可以先構造pair對象再返回
pair<int ,string> do_something(vecotr<string> &v) { if(!v.empty()) { return pair<int ,string>(v.back().size(),v.back());//也可使用make_pair來生成pair對象
} else { return pair<int ,string>(); } }
6.map的迭代器
當我們對map的迭代器進行解引用的時候我們得到的是value_type類型,也就是一個pair類型,要注意的是其first成員是const的,second成員是非常量成員,很明顯我們不能改變map關鍵字,但我們可以改變關鍵字所關聯的值,我們可以使用迭代器來遍歷我們的map對象
auto map_iter=myMap.cbegin(); while(map_iter!=myMap.cend()) { cout<<"key: "<<map_iter->first<<"value: "<<map_iter->second<<endl; ++map_iter; }
注意:由於map中的關鍵字是const,我們一般不對map使用泛型算法!
7.向map添加元素
我們使用insert對map進行元素添加操作,我們必須要記住的一點就是map的元素是pair類型的,下面列舉常用的insert方法:
myMap.insert({k1,v1}); myMap.insert(make_pair(k2,v2)); myMap.insert(pair<key_type,value_type>(k3,v3)); myMap.insert(map<key_type,value_type>::value_type(k4,v4));
下面列舉其他的一些添加元素的方式:
操作 | 說明 |
c.insert(v) | v為value_type對象,返回一個pair包含一個迭代器和是否成功插入的bool值,關鍵詞不存在才插入 |
c.emplace(args) | args用來構造元素,返回一個pair包含一個迭代器和是否成功插入的bool值,關鍵詞不在才插入 |
c.insert(b,e) | b和e是迭代器,指定多個元素插入,返回void |
c.insert(il) | il花括號列表形式,返回void |
c.insert(p.v) | 和insert(v)類似,p是迭代器,指定從哪里開始搜索新元素應該存儲的位置,返回值為一個迭代器,指出具有給定關鍵字的元素 |
c.emplace(p,args) | 和c.emplace(args)類似,p是迭代器,指定從哪里開始搜索新元素應該存儲的位置,返回值為一個迭代器,指出具有給定關鍵字的元素 |
7.1 檢測insert的返回值
添加單一元素的insert和emplace返回值一個pair,告訴我們插入是否成功,pair的first是一個迭代器,指向具有給定關鍵字的元素,second是一個bool型,如果插入成功為true,否則為false。如果關鍵字已經在map中那么insert和emplace什么也不做。
8.刪除元素
使用erase函數來執行map的刪除操作:
操作 | 說明 |
c.erase(k) | 刪除c中關鍵詞為k的元素,返回值為size_type類型,指出刪除元素的數目,因為map中不允許重復,返回值為0或者1 |
c.erase(p) | 從c中刪除迭代器p指定的元素,p必須指向一個真實存在的元素,返回值指向p之后元素的迭代器,如果p指向c的微元素,那么將返回c.end() |
c.erase(b,e) | 刪除迭代器對b和e所表示返回的元素,返回值迭代器e |
9. map的下標操作
map提供了下標操作和at函數操作。我們對map使用下標操作要注意下標是關鍵字,還要注意的是對不存在map中的關鍵字使用了下標操作,會添加一個具有該關鍵字的元素到map中。
操作 |
說明 |
c[k] | 返回關鍵字為k的元素,如果k不在c中,添加一個關鍵字為k的元素,對其進行初始化 |
c.at(k) | 訪問關鍵字為k的元素,帶參數檢查,如果k不在c中,則返回out_of_range異常 |
9.1使用下標操作的返回值
當我們對一個map進行下標操作的時候,會獲得mapped_type對象,但當解引用map的迭代器時,會得到一個value_type對象,如果關鍵字不存在map中,下標運算依然會添加一個具有該關鍵字的新元素。在我們不確定一個元素是否在map中,且不想在map中進行添加就不能使用下標操作。
10.訪問元素
當我們要確定一個元素是否存在map中,使用find是最佳的選擇,對於不允許重復關鍵字的map來說,使用count函數返回的關鍵字計數只能為0和1。對於map元素的訪問還有如下的操作:
操作 | 說明 |
c.find(k) | 返回一個迭代器,指向第一個關鍵字為k的元素,如果不在map中,則返回尾后迭代器c.end() |
c.count(k) | 返回關鍵字等於k的元素數量,對於map返回值只能為0和1 |
c.lower_bound(k) | 返回一個迭代器,指向第一個關鍵字不小於k的元素 |
c.upper_bound(k) | 返回一個迭代器,指向第一個關鍵字大於k的元素 |
c.equal_range(k) | 返回一個迭代器pair,表示關鍵字等於k元素的范圍,如果k不存在,則pair的數據成員全是c.end() |
備注:如果使用lower_bound和upper_bound匹配關鍵字k,返回了相同的迭代器,那么關鍵字k不在map中。