原文鏈接:https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html
Map是STL的一個關聯容器,它提供一對一(其中第一個可以稱為關鍵字,每個關鍵字只能在map中出現一次,第二個可以稱為該關鍵字的值)的數據 處理能力,由於這個特性,它完成有可能在我們處理一對一數據的時候,在編程上提供快速通道。這里說下map內部數據的組織,map內部自建一顆紅黑樹(一 種非嚴格意義上的平衡二叉樹),這顆樹具有對數據自動排序的功能,所以在map內部所有的數據都是有序的,后邊我們會見識到有序的好處。
1、map簡介
map是一類關聯式容器。它的特點是增加和刪除節點對迭代器的影響很小,除了那個操作節點,對其他的節點都沒有什么影響。
對於迭代器來說,可以修改實值,而不能修改key。
2、map的功能
自動建立Key - value的對應。key 和 value可以是任意你需要的類型。
根據key值快速查找記錄,查找的復雜度基本是Log(N),如果有1000個記錄,最多查找10次,1,000,000個記錄,最多查找20次。
快速插入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容器后,我們就可以往里面插入數據了。這里講三種插入數據的方法:
#include<map> #include<string> #include<iostream>
using namespace std; 1.// 用insert插入pair數據
int main(){ map<int ,string> mapst; mapst.insert(pair<int,string>(1,"student1")); mapst.insert(pair<int,string>(2,"student2")); mapst.insert(pair<int,string>(3,"student3")); map<int,string>::iterator it; for(it=mapst.begin();it!=mapst.end();it++) cout<<it->first<<" "<<it->second<<endl; return 0; } 2.// 用insert函數插入value_type
int main(){ map<int,string> mapst; mapst.insert(map<int,string>::value_type(1,"student1")); mapst.insert(map<int,string>::value_type(2,"student2")); mapst.insert(map<int,string>::value_type(3,"student3")); map<int,string> ::iterator it; for(it=mapst.begin();it!=mapst.end();it++) cout<<it->first<<" "<<it->second<<endl; } 3.// 用數組方式插入
int main(){ map<int,string> mapst; mapst[1]="student1"; mapst[2]="student2"; mapst[3]="student3"; map<int,string> ::iterator it; for(it=mapst.begin();it!=mapst.end();it++) cout<<it->first<<" "<<it->second<<endl; }
以上三種用法,雖然都可以實現數據的插入,但是他們是有區別的,當然了第一種和第二種在效果上是一樣的,用insert函數插入數據,在數據的插入上設計到集合的唯一性這個概念,即當map中有這個關鍵字時,insert操作是插入數據不了的,但是用數組方式就不同了,它可以覆蓋以前該關鍵字對應的值,用程序說明:
mapst.insert(map<int,string>::value_type(1,"student1")); mapst.insert(map<int,string>::value_type(1,"student2"));
上面這兩條語句執行后,map中1這個關鍵字對應的值是“student_one”,第二條語句並沒有生效,那么這就涉及到我們怎么知道insert語句是否插入成功的問題了,可以用pair來獲得是否插入成功,程序如下
pair<map<int, string>::iterator, bool> Insert_Pair;
Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, "student_one"));
我們通過pair的第二個變量來知道是否插入成功,它的第一個變量返回的是一個map的迭代器,如果插入成功的話Insert_Pair.second應該是true的,否則為false。
下面給出完成代碼,演示插入成功與否問題:
#include<map> #include<string> #include<algorithm> #include<iostream>
using namespace std; int main(){ map<int,string> mapst; pair<map<int ,string>::iterator,bool>insert_pair; insert_pair=mapst.insert(map<int,string>::value_type(1,"student1")); if(insert_pair.second==true) cout<<"insert successfully"<<endl; else cout<<"insert failure"<<endl; insert_pair=mapst.insert(pair<int,string>(1,"student2")); if(insert_pair.second==true) cout<<"insert successfully"<<endl; else cout<<"insert failure"<<endl; map<int,string>::iterator it; for(it=mapst.begin();it!=mapst.end();it++) cout<<it->first<<" "<<it->second<<endl; }
運行結果:
insert successfully
insert failure
1 student1
用數組插入在數據覆蓋上的效果
#include<map> #include<string> #include<algorithm> #include<iostream>
using namespace std; int main(){ map<int,string> mapst; mapst[1]="student1"; mapst[1]="student2"; mapst[2]="student3"; map<int,string>::iterator it; for(it=mapst.begin();it!=mapst.end();it++) cout<<it->first<<" "<<it->second<<endl; return 0; }
運行結果
1 student2
2 student3
6、map的大小
在往map里面插入了數據,我們怎么知道當前已經插入了多少數據呢,可以用size函數,用法如下:
Int nSize = mapStudent.size();
7、 數據的遍歷
這里也提供三種方法,對map進行遍歷
第一種:應用前向迭代器,上面舉例程序中到處都是了,略過不表
第二種:應用反相迭代器
#include<map> #include<string> #include<algorithm> #include<iostream>
using namespace std; int main(){ map<int,string> mapst; mapst.insert(pair<int,string>(1,"student1")); mapst.insert(pair<int,string>(2,"student2")); mapst.insert(pair<int,string>(3,"student3")); map<int,string>::reverse_iterator it; for(it=mapst.rbegin();it!=mapst.rend();it++) cout<<it->first<<" "<<it->second<<endl; return 0; }
運行結果:
3 student3
2 student2
1 student1
第三種,用數組的形式,程序說明:
#include<map> #include<string> #include<algorithm> #include<iostream>
using namespace std; int main(){ map<int,string> mapst; mapst.insert(pair<int,string>(1,"student1")); mapst.insert(pair<int,string>(2,"student2")); mapst.insert(pair<int,string>(3,"student3")); int nsize=mapst.size(); //此處應注意,應該是 for(int i = 1; i <= nsize; i++) //而不是 for(int i = 0; i < nsize; i++)
for(int i=1;i<=nsize;i++) cout<<mapst[i]<<endl; return 0; }
運行結果:
student1
student2
student3
8、查找並獲取map中的元素(包括判定這個關鍵字是否在map中出現)
在這里我們將體會,map在數據插入時保證有序的好處。
要判定一個數據(關鍵字)是否在map中出現的方法比較多,這里標題雖然是數據的查找,在這里將穿插着大量的map基本用法。
這里給出三種數據查找方法 :
第一種:用count函數來判定關鍵字是否出現,其缺點是無法定位數據出現位置,由於map的特性,一對一的映射關系,就決定了count函數的返回值只有兩個,要么是0,要么是1,出現的情況,當然是返回1了
第二種:用find函數來定位數據出現位置,它返回的一個迭代器,當數據出現時,它返回數據所在位置的迭代器,如果map中沒有要查找的數據,它返回的迭代器等於end函數返回的迭代器。
查找map中是否包含某個關鍵字條目用find()方法,傳入的參數是要查找的key,在這里需要提到的是begin()和end()兩個成員,
分別代表map對象中第一個條目和最后一個條目,這兩個數據的類型是iterator.
程序說明:
#include<map> #include<string> #include<algorithm> #include<iostream>
using namespace std; int main(){ map<int,string> mapst; mapst.insert(pair<int,string>(1,"student1")); mapst.insert(pair<int,string>(2,"student2")); mapst.insert(pair<int,string>(3,"student3")); int nsize=mapst.size(); map<int,string>::iterator it; it=mapst.find(1); if(it!=mapst.end()) cout<<"Find,the value is"<<it->second<<endl; else cout<<"Do not Find"<<endl; return 0; }
運行結果:
Find,the value is student1
通過map對象的方法獲取的iterator數據類型是一個std::pair對象,包括兩個數據 iterator->first和 iterator->second分別代表關鍵字和存儲的數據。
第三種:這個方法用來判定數據是否出現,
lower_bound函數用法,這個函數用來返回要查找關鍵字的下界(是一個迭代器)
upper_bound函數用法,這個函數用來返回要查找關鍵字的上界(是一個迭代器)
例如:map中已經插入了1,2,3,4的話,如果lower_bound(2)的話,返回的2,而upper_bound(2)的話,返回的就是3
Equal_range函數返回一個pair,pair里面第一個變量是Lower_bound返回的迭代器,pair里面第二個迭代器是Upper_bound返回的迭代器,如果這兩個迭代器相等的話,則說明map中不出現這個關鍵字。
#include<map> #include<string> #include<iostream>
using namespace std; int main(){ map<int,string>mapst; mapst[1]="student1"; mapst[3]="student3"; mapst[5]="student5"; map<int,string>::iterator it; it=mapst.lower_bound(1); cout<<it->second<<endl; it=mapst.lower_bound(2); cout<<it->second<<endl; it=mapst.lower_bound(3); cout<<it->second<<endl; it=mapst.upper_bound(2); cout<<it->second<<endl; it=mapst.upper_bound(3); cout<<it->second<<endl; pair<map<int, string>::iterator, map<int, string>::iterator> mappair; mappair = mapst.equal_range(2); if(mappair.first == mappair.second) cout<<"Do not Find"<<endl; else cout<<"Find"<<endl; mappair = mapst.equal_range(3); if(mappair.first == mappair.second) cout<<"Do not Find"<<endl; else cout<<"Find"<<endl; return 0; }
運行結果:
student1
student3
student3
student3
student5
Do not Find
Find
9、 從map中刪除元素
移除某個map中某個條目用erase()
該成員方法的定義如下:
iterator erase(iterator it);//通過一個條目對象刪除
iterator erase(iterator first,iterator last)//刪除一個范圍
size_type erase(const Key&key);//通過關鍵字刪除
clear()就相當於enumMap.erase(enumMap.begin(),enumMap.end());
這里要用到erase函數,它有三個重載了的函數,下面在例子中詳細說明它們的用法:
#include<map> #include<string> #include<iostream>
using namespace std; int main(){ map<int,string>mapst; mapst.insert(pair<int, string>(1, "student1")); mapst.insert(pair<int, string>(2, "student2")); mapst.insert(pair<int, string>(3, "student3")); map<int,string>::iterator it; it=mapst.find(1); mapst.erase(it); //擦去容器1 // int n=mapst.erase(1); //如果刪除了會返回1,否則返回0 // mapst.erase(mapst.begin(),mapst.end()); //用迭代器,成片的刪除 一下代碼把整個map清空
for(it=mapst.begin();it!=mapst.end();it++) cout<<it->first<<" "<<it->second<<endl; return 0; }
運行結果:
2 student2
3 student3
10. map中的swap用法
map中的swap不是一個容器中的元素交換,而是兩個容器所有元素的交換。
11.其他函數
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的函數