需要引入的头文件不同
map: #include < map >
unordered_map: #include < unordered_map >
内部实现机理不同
map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树
,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。
map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
优缺点以及适用处
map
优点:
有序性
,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作.
红黑树
,内部实现一个红黑书使得map的很多操作在logn的时间复杂度下就可以实现,因此效率非常的高
缺点:
空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点,孩子节点以及红/黑性质,使得每一个节点都占用大量的空间.
适用于那些有顺序要求的问题,用map会更高效一些.
unordered_map
优点:
因为内部实现了哈希表,因此其查找速度非常的快
缺点:
哈希表的建立比较耗费时间
对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
map和unordered_map的使用
unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。
下面看看unordered_map使用例子
int main()
{
//1.插入元素,和map用法一样,可以看看我之前的map文章。
unordered_map<int, string> m_unorderdMap;
m_unorderdMap.insert(make_pair(1, "jack1"));
m_unorderdMap.insert(make_pair(3, "jack3"));
m_unorderdMap.insert(make_pair(4, "jack4"));
m_unorderdMap.insert(make_pair(2, "jack2"));
m_unorderdMap.insert(make_pair(2, "jack2222"));//不会插入
//2.遍历
for (auto node :m_unorderdMap)
{
cout << node.first << " " << node.second << endl;
}
//3.随机访问
auto it = m_unorderdMap[5];
cout << it.c_str() << endl;
//再次遍历
cout << "使用数组下标[]方式取一个没有的值后遍历:\n";
for (auto node : m_unorderdMap)
{
cout << node.first << " " << node.second << endl;
}
//4.判断是否有元素
if (m_unorderdMap.empty())
{
cout << "m_unorderdMap 是空的!\n";
}
else
{
cout << "m_unorderdMap 不是空的!\n";
}
//5.查找1,count 如果个数不为0就说明找到了。
int ncount = m_unorderdMap.count(1);
cout << "1的个数:" << ncount << endl;
ncount = m_unorderdMap.count(2);
cout << "2的个数:" << ncount << endl;
//6.查找2 find
std::unordered_map<int,string >::iterator itx = m_unorderdMap.find(2);
if (itx != m_unorderdMap.end())
{
cout << "找到:"<<itx->first<<" " <<itx->second << endl;
}
cout << endl;
system("pause");
return 0;
}
结果:
从结果可以看出是没有顺序的,和map的性质一样,它不允许插入相同的元素。
注意:
unordered_map, 它与 map的区别就是,map是按照operator<
比较判断元素是否相同,以及比较元素的大小,然后选择合适的位置插入到树中。所以,如果对map进行遍历(中序遍历)的话,输出的结果是有序的。顺序就是按照operator< 定义的大小排序。
而unordered_map是计算元素的Hash值,根据Hash值判断元素是否相同。所以,对unordered_map进行遍历,结果是无序的。
用法的区别就是,map 的key需要定义operator<
。 而unordered_map需要定义hash_value函数并且重载operator==
。对于内置类型,如string,这些都不用操心。对于自定义的类型做key,就需要自己重载operator<
或者hash_value()了。
如果key是自定义类型时,直接使用std::unordered_map,编译时会报错,错误信息为:”error C2338: The C++ Standard doesn’t provide a hash for this type.”大意是,C++标准库没有为该类型提供hash操作!因此,针对自定义类型,我们在使用std::unordered_map时必须提供自定义的Hash函数。
参考:https://blog.csdn.net/qq_21997625/article/details/84672775
参考: