map,multimap,unordered_map,unordered_multimap的详解
1,map簡介
map是STL的一個關聯容器,它提供一對一的hash。
- 第一個可以稱為關鍵字(key),每個關鍵字只能在map中出現一次;
- 第二個可能稱為該關鍵字的值(value);
map以模板(泛型)方式實現,可以存儲任意類型的數據,包括使用者自定義的數據類型。Map主要用于資料一對一映射(one-to-one)的情況,map內部的實現自建一顆紅黑樹,這顆樹具有對數據自動排序的功能。在map內部所有的數據都是有序的,后邊我們會見識到有序的好處。比如一個班級中,每個學生的學號跟他的姓名就存在著一對一映射的關系。? ? ?
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ??
?
2,map的功能
自動建立key?- value的對應。key 和 value可以是任意你需要的類型,包括自定義類型。
3,使用map
使用map得包含map類所在的頭文件
#include <map>??//注意,STL頭文件沒有擴展名.h
map對象是模板類,需要關鍵字和存儲對象兩個模板參數:
std:map<int, string>?personnel;
這樣就定義了一個用int作為索引,并擁有相關聯的指向string的指針.
為了使用方便,可以對模板類進行一下類型定義,
typedef?map<int,CString>?UDT_MAP_INT_CSTRING;
UDT_MAP_INT_CSTRING enumMap;
4,map的構造函數
map共提供了6個構造函數,這塊涉及到內存分配器這些東西,略過不表,在下面我們將接觸到一些map的構造方法,這里要說下的就是,我們通常用如下方法構造一個map:
map<int,?string>?mapStudent;
5,插入元素
// 定義一個map對象 map<int,?string>?mapStudent;// 第一種 用insert函數插入pair mapStudent.insert(pair<int, string>(000, "student_zero"));// 第二種 用insert函數插入value_type數據 mapStudent.insert(map<int, string>::value_type(001, "student_one"));// 第三種 用"array"方式插入 mapStudent[123] = "student_first"; mapStudent[456] = "student_second";以上三種用法,雖然都可以實現數據的插入,但是它們是有區別的,當然了第一種和第二種在效果上是完成一樣的,用insert函數插入數據,在數據的?插入上涉及到集合的唯一性這個概念,即當map中有這個關鍵字時,insert操作是不能在插入數據的,但是用數組方式就不同了,它可以覆蓋以前該關鍵字對?應的值,用程序說明如下:
?
上面這兩條語句執行后,map中001這個關鍵字對應的值是“student_one”,第二條語句并沒有生效,那么這就涉及到我們怎么知道insert語句是否插入成功的問題了,可以用pair來獲得是否插入成功,程序如下
// 構造定義,返回一個pair對象 pair<iterator,bool> insert (const value_type& val);pair<map<int, string>::iterator, bool> Insert_Pair;Insert_Pair = mapStudent.insert(map<int, string>::value_type (001, "student_one"));if(!Insert_Pair.second)cout << ""Error insert new element" << endl;?
我們通過pair的第二個變量來知道是否插入成功,它的第一個變量返回的是一個map的迭代器,如果插入成功的話Insert_Pair.second應該是true的,否則為false。
6,?查找元素
當所查找的關鍵key出現時,它返回數據所在對象的位置,如果沒有,返回iter與end函數的值相同。
// find 返回迭代器指向當前查找元素的位置否則返回map::end()位置 iter = mapStudent.find("123");if(iter != mapStudent.end())cout<<"Find, the value is"<<iter->second<<endl; elsecout<<"Do not Find"<<endl;7,?刪除與清空元素
//迭代器刪除 iter = mapStudent.find("123"); mapStudent.erase(iter);//用關鍵字刪除 int n = mapStudent.erase("123"); //如果刪除了會返回1,否則返回0//用迭代器范圍刪除 : 把整個map清空 mapStudent.erase(mapStudent.begin(), mapStudent.end()); //等同于mapStudent.clear()8,map的大小
在往map里面插入了數據,我們怎么知道當前已經插入了多少數據呢,可以用size函數,用法如下:
int nSize = mapStudent.size();?9,map的基本操作函數:
?C++?maps是一種關聯式容器,包含“關鍵字/值”對
?????begin()?????????返回指向map頭部的迭代器
?????clear()????????刪除所有元素
?????count()?????????返回指定元素出現的次數
?????empty()?????????如果map為空則返回true
?????end()???????????返回指向map末尾的迭代器
?????equal_range()???返回特殊條目的迭代器對
?????erase()?????????刪除一個元素
?????find()??????????查找一個元素
?????get_allocator()?返回map的配置器
?????insert()????????插入元素
?????key_comp()??????返回比較元素key的函數
?????lower_bound()???返回鍵值>=給定元素的第一個位置
?????max_size()??????返回可以容納的最大元素個數
?????rbegin()????????返回一個指向map尾部的逆向迭代器
?????rend()??????????返回一個指向map頭部的逆向迭代器
?????size()??????????返回map中元素的個數
?????swap()???????????交換兩個map
?????upper_bound()????返回鍵值>給定元素的第一個位置
?????value_comp()?????返回比較元素value的函數
?
multimap基本用法
multimap和map的功能類似,就不一一介紹了,下面主要說一下這兩者的不同:
1、multimap中的key可以重復
2、multimap中沒有重載operator[ ]功能
?
談談unordered_map和map的區別
1、內部實現機理不同:
map :map內部實現了一個紅黑樹(紅黑樹是非嚴格平衡二叉搜索樹,而AVL是嚴格平衡二叉搜索樹),紅黑樹具有自動排序的功能,因此map內部的所有元素都是有序的,紅黑樹的每一個節點都代表著map的一個元素。因此,對于map進行的查找、刪除,添加等一系列的操作都相當于是對紅黑樹進行的操作。map中的元素是按照二叉搜索樹 (又名兒茶查找樹、二叉排序樹–特點就是左子樹上所有節點的鍵值都小于根節點的鍵值,右子樹所有節點的鍵值都大于根結點的鍵值)存儲的,使用中序遍歷可將鍵值按照從小到大遍歷出來。
unordered_map :unordered_map內部實現了一個哈希表 (也叫散列表,通過把關鍵碼值映射到Hash表中一個位置來訪問記錄,查找的時間復雜度可達到O(1),其在海量數據處理中有著廣泛應用)。因此,其元素的排列順序都是無序的。哈表的概念見:詳談哈希表。
2、談談各自的優缺點:
- map
-
1、優點:
????(1)有序性,這是map結構最大的有點,其元素的有序性在很多應用中都會簡化很多的操作。
????(2)紅黑樹,內部實現一個紅黑樹使得map的很多操作在lgn的時間復雜度下就可以實現,因此效率非常的高。
2、缺點:空間占用率高,因為map內部實現了紅黑樹,雖然提高了運行效率,但是因為每一個節點都需要額外保存父節點、孩子節點和紅/黑性質,使得每一個節點都占用大量的空間。
3、適用處:對于那些有順序要求的問題,用map會更高效一些。
- unordered_map
-
1、優點:因為內部實現了哈希表,因此其查找速度非常的快。
2、缺點:哈希表的建立比較耗費時間
3、適用處:對于查找問題,unordered_map?會更加高效一些,因此遇到查找問題,常會考慮一下用unordered_map
3、總結:
1、內存占有率的問題就轉化成紅黑樹 VS Hash表,還是unorder_map占用的內存要高。
2、但是unorder_map執行效率要比map高很多
3、對于unordered_map 或unordered_set 容器,其遍歷順序與創建該容器時輸入的順序不一定相同,因為遍歷是按照哈希表從前往后依次遍歷的。
?
?
?
unordered_multimap用法
unordered_map?是一個封裝哈希表的無序容器。容器中每個元素都是 key/value,每個 key 僅可出現一次。
unordered_multimap?是一個封裝哈希表的無序容器。容器中每個元素都是 key/value,每個 key 可重復出現。
unordered_map?和?unordered_multimap?都是基于哈希表實現的,而且沖突策略采用的是鏈地址法。示意圖如下:
? ? ? ? ? ? ?
操作與unordered_map相似
總結
以上是生活随笔為你收集整理的map,multimap,unordered_map,unordered_multimap的详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LRU原理及其实现(C++)
- 下一篇: C++模板的那丢丢事儿