1. 程式人生 > >【C++】STL常用容器總結之八:對映map

【C++】STL常用容器總結之八:對映map

9、對映map

Map是鍵-值對的集合,map中的所有元素都是pair,可以使用鍵作為下標來獲取一個值。Map中所有元素都會根據元素的值自動被排序,同時擁有實值value和鍵值key,pair的第一元素被視為鍵值,第二元素被視為實值,同時map不允許兩個元素有相同的鍵值。要使用map物件,必須包含map的標頭檔案#include<map>

1、map的建構函式

在定義map物件時,必須分別指明鍵和值的型別。Map建立key-value的一種對映。

1.map<key, value> m;

建立一個名為m的空map物件,其鍵和值的型別分別為key和value。

2.map<key, value> m(m2);

建立m2的副本m,m與m2必須有相同的鍵型別和值型別。

3.map<key, value> m(b,e);

建立map型別的物件m,儲存迭代器b和e標記的範圍內所有元素的副本,元素的型別必須能轉換為pair

4.map<key, value, comp> mp;

comp可選,為鍵值對存放策略,即鍵的比較函式,預設標準庫使用鍵型別定義的 < 操作符來實現鍵的比較。所用的比較函式必須在鍵型別上定義嚴格的弱排序,可將其理解為鍵型別資料上的“小於”關係。在實際應用中,鍵型別必須能定義 < 操作符。對於鍵型別,其唯一的約束就是必須支援 < 操作符。

2、map定義的型別

map<key, value> ::key_type;  // 在map容器中,用作索引的鍵的型別
map<key, value> ::mapped_type;  // 在map容器中,鍵所關聯的值的型別
map<key, value> ::value_type;  // 一個pair型別,它的first元素具有const map<key, value> ::key_type型別,而second元素則為map<key, value> :: mapped_type型別。

在學習map介面時,謹記其value_type是pair型別,它的值成員可以修改(second成員),但鍵成員不能修改。這個value_type相當於map的元素型別,而不是鍵所對應的值的型別。
對map迭代器進行解引用將產生pair型別的物件,它的first成員存放鍵,為const,而second成員存放值。

3、map容器的一些操作

給map容器新增元素可通過兩種方式實現:
1. 通過insert成員函式實現。
2. 通過下標操作符獲取元素,然後給獲取的元素賦值。
map物件的訪問可通過下標和迭代器兩種方式實現:
1. map的下標是鍵,返回的是特定鍵所關聯的值。
2. 使用迭代器訪問,iter->first指向元素的鍵,iter->second指向鍵對應的值。
使用下標訪問map容器與使用下標訪問vector的行為截然不同:用下標訪問map中不存在的元素將導致在map容器中新增一個新的元素,這個元素的鍵即為該下標值,鍵所對應的值為空。

4、map容器與雜湊表

對於map容器,使用其下標行為一次訪問一系列的相同型別的元素,則可以將這個過程理解為構造了這些元素的一個雜湊表,以統計輸入單詞的出現次數為例:

map<string, int> word_count;
string word;
while(cin>>word)
    ++word_count[word];  // 相當於生成了一個雜湊表word_count

在單詞的第一次出現時,會在word_count中建立並插入一個以該單詞為索引的新元素,同時將它的值初始化為0。然後其值立即加1,所以每次在map中新增新元素時,所統計的次數正好從1開始。需要注意的是,使用map建立的雜湊表已經按鍵值進行了排序,所以序列的順序已經不再是原始的輸入順序了。

5、map的成員函式

1、不修改map物件的查詢操作:

m.count(k);  // 返回m中鍵值等於k的元素的個數。
m.find(k);  // 如果m中存在按k索引的元素,則返回指向該元素的迭代器。如果不存在,則返回結束遊標end()。

對於map物件,由於map中不存在相同的兩個或者多個鍵,所以count成員的返回值只能是0或者1,用於檢查map物件中某鍵是否存在。find成員返回的是指向元素的迭代器,如果元素不存在,則返回end迭代器,用於讀取元素而又不插入元素。

2、從map物件中刪除元素:

m.erase(k);  // 刪除m中鍵為k的元素,返回size_type型別的值,表示刪除元素的個數。
m.erase(p);  // 從m中刪除迭代器p所指向的元素,p必須指向m中確實存在的元素,而且不能等於m.end(),返回void型別。
m.erase(iterator first, iterator last);  // 刪除一個範圍,返回void型別。

3、map容器提供的insert操作:

m.insert(e) ;
e是一個用在m上的value_type型別的值。如果鍵e.first不在m中,則插入一個值為e.second的新元素;如果該鍵在m中已存在,那麼不進行任何操作。該函式返回一個pair型別物件,包含指向鍵為e.first的元素的map迭代器,以及一個bool型別的物件,表示是否插入了該元素。
m.insert(beg, end);
beg和end是標記元素範圍的迭代器,對於該範圍內的所有元素,如果它的鍵在m中不存在,則將該鍵及其關聯的值插入到m。 返回void型別。
m.insert(iter, e);
e是value_type型別的值,如果e.first不在m中,則建立新元素,並以迭代器iter為起點搜尋新元素儲存的位置,返回一個迭代器,指向m中具有給定鍵的元素。
在新增新的map元素時,使用insert成員可避免使用下標操作符帶來的副作用:不必要的初始化。