1. 簡介
map和unordered_map都是c++中可以充當字典(key-value)來用的數據類型,但是其基本實現是不一樣的。
2. map
對於map的底層原理,是通過紅黑樹(一種非嚴格意義上的平衡二叉樹)來實現的,因此map內部所有的數據都是有序的,map的查詢、插入、刪除操作的時間復雜度都是O(logn)。此外,map的key需要定義operator <,對於一般的數據類型已被系統實現,若是用戶自定義的數據類型,則要重新定義該操作符。
map的基本操作如下
#include<iostream> #include<map> #include<string> using namespace std; int main() { // 構造函數 map<string, int> dict; // 插入數據的三種方式 dict.insert(pair<string,int>("apple",2)); dict.insert(map<string, int>::value_type("orange",3)); dict["banana"] = 6; // 判斷是否有元素 if(dict.empty()) cout<<"該字典無元素"<<endl; else cout<<"該字典共有"<<dict.size()<<"個元素"<<endl; // 遍歷 map<string, int>::iterator iter; for(iter=dict.begin();iter!=dict.end();iter++) cout<<iter->first<<ends<<iter->second<<endl; // 查找 if((iter=dict.find("banana"))!=dict.end()) // 返回一個迭代器指向鍵值為key的元素,如果沒找到就返回end() cout<<"已找到banana,其value為"<<iter->second<<"."<<endl; else cout<<"未找到banana."<<endl; if(dict.count("watermelon")==0) // 返回鍵值等於key的元素的個數 cout<<"watermelon不存在"<<endl; else cout<<"watermelon存在"<<endl; pair<map<string, int>::iterator, map<string, int>::iterator> ret; ret = dict.equal_range("banana"); // 查找鍵值等於 key 的元素區間為[start,end),指示范圍的兩個迭代器以 pair 返回 cout<<ret.first->first<<ends<<ret.first->second<<endl; cout<<ret.second->first<<ends<<ret.second->second<<endl; iter = dict.lower_bound("boluo"); // 返回一個迭代器,指向鍵值>=key的第一個元素。 cout<<iter->first<<endl; iter = dict.upper_bound("boluo"); // 返回一個迭代器,指向值鍵值>key的第一個元素。 cout<<iter->first<<endl; return 0; }
注意如果定義了map<string,int>這個類型,需要在頭文件中包含“#include<string>”,這是因為默認的string是系統的xstring對象,但是沒有定義operator<,從而報錯。map用到自定義的類型,一定要定義operator<,具體用法如下。
struct person { string name; int age; person(string name, int age) { this->name = name; this->age = age; } bool operator < (const person& p) const { return this->age < p.age; } }; map<person,int> m;
3. unordered_map
unordered_map和map類似,都是存儲的key-value的值,可以通過key快速索引到value。不同的是unordered_map不會根據key的大小進行排序,存儲時是根據key的hash值判斷元素是否相同,即unordered_map內部元素是無序的。unordered_map的底層是一個防冗余的哈希表(開鏈法避免地址沖突)。unordered_map的key需要定義hash_value函數並且重載operator ==。
哈希表最大的優點,就是把數據的存儲和查找消耗的時間大大降低,時間復雜度為O(1);而代價僅僅是消耗比較多的內存。哈希表的查詢時間雖然是O(1),但是並不是unordered_map查詢時間一定比map短,因為實際情況中還要考慮到數據量,而且unordered_map的hash函數的構造速度也沒那么快,所以不能一概而論,應該具體情況具體分析。
unordered_map的基本操作
#include<string> #include<iostream> #include<unordered_map> using namespace std; int main() { unordered_map<string, int> dict; // 聲明unordered_map對象 // 插入數據的三種方式 dict.insert(pair<string,int>("apple",2)); dict.insert(unordered_map<string, int>::value_type("orange",3)); dict["banana"] = 6; // 判斷是否有元素 if(dict.empty()) cout<<"該字典無元素"<<endl; else cout<<"該字典共有"<<dict.size()<<"個元素"<<endl; // 遍歷 unordered_map<string, int>::iterator iter; for(iter=dict.begin();iter!=dict.end();iter++) cout<<iter->first<<ends<<iter->second<<endl; // 查找 if(dict.count("boluo")==0) cout<<"can't find boluo!"<<endl; else cout<<"find boluo!"<<endl; if((iter=dict.find("banana"))!=dict.end()) cout<<"banana="<<iter->second<<endl; else cout<<"can't find boluo!"<<endl; return 0; }
nordered_map用到自定義的類型,需要對key定義hash_value函數並且重載operator ==,具體用法請參考文獻。