1. 简介
map和unordered_map都是c++中可以充当字典(key-value)来用的数据类型,但是其基本实现是不一样的。
2.map
对于map的底层原理,是通过红黑树(一种非严格意义上的平衡二叉树)来实现的,因此map内部所有的数据都是有序的,map的查询、插入、删除操作的时间复杂度都是O(logn)。此外,map的key需要定义operator <,对于一般的数据类型已被系统实现,若是用户自定义的数据类型,则要重新定义该操作符。
map的基本操作如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #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()) cout<<"已找到banana,其value为"<<iter->second<<"."<<endl; else cout<<"未找到banana."<<endl; if(dict.count("watermelon")==0) cout<<"watermelon不存在"<<endl; else cout<<"watermelon存在"<<endl;
pair<map<string, int>::iterator, map<string, int>::iterator> ret; ret = dict.equal_range("banana"); cout<<ret.first->first<<ends<<ret.first->second<<endl; cout<<ret.second->first<<ends<<ret.second->second<<endl; iter = dict.lower_bound("boluo"); cout<<iter->first<<endl; iter = dict.upper_bound("boluo"); cout<<iter->first<<endl; return 0; }
|
注意如果定义了map<string,int>
这个类型,需要在头文件中包含#include<string>
,这是因为默认的string是系统的xstring对象,但是没有定义operator<,从而报错。map用到自定义的类型,一定要定义operator<,具体用法如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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的基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include<string> #include<iostream> #include<unordered_map> using namespace std;
int main() { unordered_map<string, int> dict;
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; }
|
unordered_map用到自定义的类型,需要对key定义hash_value函数并且重载operator ==,具体用法请参考文献3(有空再来补个示例)。
参考文献
- C++11 新特性: unordered_map 与 map 的对比
2.C++ STL之map与unordered_map
3.std::unordered_map(提供自己的Hash函数和等价准则)
4.https://blog.csdn.net/jingyi130705008/article/details/82633778