unordered_map(hash_map)和map的比较

测试代码:

#include <iostream>
using namespace std;
#include <string>
#include <windows.h>
#include <string.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <map>
const int maxval = 2000000 * 5;
#include <unordered_map>

void map_test()
{
    printf("map_test\n");
    map<int, int> mp;
    clock_t startTime, endTime;
    startTime = clock();
    for (int i = 0; i < maxval; i++)
    {
        mp[rand() % maxval]++;
    }
    endTime = clock();
    printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    printf("insert finish\n");
    startTime = clock();
    for (int i = 0; i < maxval; i++)
    {
        if (mp.find(rand()%maxval) == mp.end())
        {
            //printf("not found\n");
        }
    }
    endTime = clock();
    printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    printf("find finish\n");

    startTime = clock();
    for(auto it = mp.begin(); it!=mp.end(); it++)
    {

    }
    endTime = clock();
    printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    printf("travel finish\n");

    printf("------------------------------------------------\n");
}

void hash_map_test()
{
    printf("hash_map_test\n");
    unordered_map<int, int> mp;
    clock_t startTime, endTime;
    startTime = clock();
    for (int i = 0; i < maxval; i++)
    {
        mp[rand() % maxval] ++;
    }
    endTime = clock();
    printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    printf("insert finish\n");
    startTime = clock();
    for (int i = 0; i < maxval; i++)
    {
        if (mp.find(rand() % maxval) == mp.end())
        {
            //printf("not found\n");
        }
    }
    endTime = clock();
    printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    printf("find finish\n");

    startTime = clock();
    for(auto it = mp.begin(); it!=mp.end(); it++)
    {

    }
    endTime = clock();
    printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
    printf("travel finish\n");

    printf("------------------------------------------------\n");
}

int main(int argc, char *argv[])
{
    srand(0);
    map_test();
    Sleep(1000);
    srand(0);
    hash_map_test();

    system("pause");
    return 0;
}

详解:

map(使用红黑树)与unordered_map(hash_map)比较

????map理论插入、查询时间复杂度O(logn)

????unordered_map理论插入、查询时间复杂度O(1)



数据量较小时,可能是由于unordered_map(hash_map)初始大小较小,大小频繁到达阈值,多次重建导致插入所用时间稍大。(类似vector的重建过程)。

哈希函数也是有消耗的(应该是常数时间),这时候用于哈希的消耗大于对红黑树查找的消耗(O(logn)),所以unordered_map的查找时间会多余对map的查找时间。



数据量较大时,重建次数减少,用于重建的开销小,unordered_map O(1)的优势开始显现



数据量更大,优势更明显



使用空间:

前半部分为map,后半部分为unordered_map

unordered_map占用的空间比map略多,但可以接受。

map和unordered_map内部实现应该都是采用达到阈值翻倍开辟空间的机制(16、32、64、128、256、512、1024……)浪费一定的空间是不可避免的。并且在开双倍空间时,若不能从当前开辟,会在其他位置开辟,开好后将数据移过去。数据的频繁移动也会消耗一定的时间,在数据量较小时尤为明显。



一种方法是手写定长开散列。这样做在数据量较小时有很好地效果(避免了数据频繁移动,真正趋近O(1))。但由于是定长的,在数据量较大时,数据重叠严重,散列效果急剧下降,时间复杂度趋近O(n)。



一种折中的方法是自己手写unordered_map(hash_map),将初始大小赋为一个较大的值。扩张可以模仿STL的双倍扩张,也可以自己采用其他方法。这样写出来的是最优的,但是实现起来极为麻烦。

综合利弊,我们组采用unordered_map。



附:使用Dev测试与VS2017测试效果相差极大???

效率差了10倍???

原因:

Dev

VS2017

在Debug下,要记录断点等调试信息,的确慢。

Release:不对源代码进行调试,编译时对应用程序的速度进行优化,使得程序在代码大小和运行速度上都是最优的。

VS2017切到release后,还更快

除了前面说的Debug与release导致效率差异外,编译器的不同也会导致效率差异。

学到了。

原文地址:https://www.cnblogs.com/mercuialC/p/9758161.html

时间: 2024-10-09 06:56:13

unordered_map(hash_map)和map的比较的相关文章

boost::unordered_map 和 std::map 的效率 与 内存比较

例子链接:http://blog.csdn.net/gamecreating/article/details/7698719 结论: unordered_map 查找效率快五倍,插入更快,节省一定内存.如果没有必要排序的话,尽量使用 hash_map(unordered_map 就是 boost 里面的 hash_map 实现). boost::unordered_map 和 std::map 的效率 与 内存比较

hash_map和map的区别(转)

这里列几个常见问题,应该对你理解和使用hash_map比较有帮助. 4.1 hash_map和map的区别在哪里? 构造函数.hash_map需要hash函数,等于函数:map只需要比较函数(小于函数). 存储结构.hash_map采用hash表存储,map一般采用红黑树(RB Tree)实现.因此其memory数据结构是不一样的. 4.2 什么时候需要用hash_map,什么时候需要用map? 总 体来说,hash_map 查找速度会比map快,而且查找速度基本和数据量大小无关,属于常数级别;

map、hash_map、unordered_map 的思考

#include <map> map<string,int> dict; map是基于红黑树实现的,可以快速查找一个元素是否存在,是关系型容器,能够表达两个数据之间的映射关系. dict.insert(make_pair("abc",1)); dict.count("mn"); 看看dict中含有 mn的个数,因为元素是唯一的,所以这个返回值只有两种情况,0或者1. (multi_map就不是这样啦) dict.find("mn&q

unordered_map 与 map 的对比(转)

unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value.不同的是unordered_map不会根据key的大小进行排序, 存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的,而map中的元素是按照二叉搜索树存储,进行中序遍历会得到有序遍历. 所以使用时map的key需要定义operator<.而unordered_map需要定义hash_value函数并且重载operator==.但是很多系统内置的数

map类与unordered_map类的区别

map类: map是一种容器,内部元素由键值对组成,键与值的数据类型可以不同,键的值是唯一的(此处的值不是键值对中的值),用于自动排序数据值,排序方式是根据某种明确.严格的弱排序标准进行的,这种排序标准是由map内部的比较对象(即map::key_comp)指定的.使用时要引入#include <map>. 在键--值这个映射关系中,元素数据值是可以更改的,但键值是常量,一旦确定无法随意更改.必须先删除与旧元素关联的键值,才能为新元素插入新键值. 实现机理:map内部实现了一个红黑树(红黑树是

STL中map与hash_map容器的选择

[转]STL中map与hash_map容器的选择 先看看alvin_lee 朋友做的解析,我觉得还是很正确的,从算法角度阐述了他们之间的问题! 实际上这个问题不光C++会遇到,其他所有语言的标准容器的实现及选择上都是要考虑的.做应用程序你可能觉得影响不大,但是写算法或者核心代码就要小心了.今天改进代码,顺便又来温习基础功课了. 还记得Herb Sutter那极有味道的<C++对话系列>么,在其中<产生真正的hash对象>这个故事里就讲了map的选择.顺便回顾一下,也讲一下我在实用中

STL中map与hash_map的比较

1. map : C++的STL中map是使用树来做查找算法; 时间复杂度:O(log2N) 2. hash_map : 使用hash表来排列配对,hash表是使用关键字来计算表位置; 时间复杂度:O(1), 最坏的时间复杂度:O(n) 总体来说:hash_map 比 map 查找速度快,而且查找速度基本和数据量大小无关,属于常数级别,节省一定内存,如果没有必要排序的话,尽量使用 hash_map . 注:hash还有hash函数的耗时.当有100w条记录的时候,map也只需要20次的比较,20

关于STL中的map和hash_map

以下全部copy于:http://blog.chinaunix.net/uid-26548237-id-3800125.html 在网上看到有关STL中hash_map的文章,以及一些其他关于STL map和hash_map的资料,总结笔记如下:     1.STL的map底层是用红黑树实现的,查找时间复杂度是log(n):     2.STL的hash_map底层是用hash表存储的,查询时间复杂度是O(1):     3.什么时候用map,什么时候用hash_map?     这个药看具体的

STL 中的map 与 hash_map的理解

可以参考侯捷编著的<STL源码剖析> STL 中的map 与 hash_map的理解 1.STL的map底层是用红黑树存储的,查找时间复杂度是log(n)级别: 2.STL的hash_map底层是用hash表存储的,查询时间复杂度是常数级别: 3.什么时候用map,什么时候用hash_map? 这个要看具体的应用,不一定常数级别的hash_map一定比log(n)级别的map要好,hash_map的hash函数以及解决地址冲突等都要耗时,而且众所周知hash表是以空间效率来换时间效率的,因而h