map unordered_map 性能对比

结论如下:

Release模式下:

1. 容量为10的时候,查找效率:map > unordered_map > hash_map

2. 容量为100的时候,查找效率:map = unordered_map > hash_map

3. 容量为1000的时候,查找效率:unordered_map > hash_map > 4倍map

4. 容量为1万的时候,查找效率:hash_map > unordered_map > 4倍map

5. 容量为10万的时候,查找效率:hash_map > unordered_map > 4倍map

6. 容量为100万的时候,查找效率:hash_map > unordered_map > 1.6倍map

7. 容量为1000万的时候,查找效率:hash_map > unordered_map > 1.4倍map

8. 容量为1亿的时候,程序崩溃了

9. debug模式下和release模式下,差距非常大,几百倍的差距。。。。。

Debug模式下:

1. 查找效率:hash_map > unordered_map > map

2. 随着容量的增加,hash_map, unordered_map的查找效率有所降低,但浮动不大毕竟是常量级别。map的效率直线下降。。。

3. 容量为一千万的时候,程序同样崩溃

实验结果如下图:

Release模式                                                                                Debug模式(注意:相比Release模式还降低了10倍的查询量)

    

代码如下:

#include<iostream>
#include<map>
#include<hash_map>
#include<unordered_map>
#include <functional>

using namespace std;


uint64_t gettimeW()
{
    uint64_t t;
    struct timespec ti;
    clock_gettime(CLOCK_MONOTONIC, &ti);
    t = (uint64_t) ti.tv_sec * 1000000000;
    t += ti.tv_nsec;
    return t;
}


// 测试函数,
// size        :    map的实际大小
// times    :    查找的轮次,每一轮次都从0查找到size-1
void test(int size, int times)
{
    cout << "size=" << size << "; times=" << times << endl;

    auto cur = gettimeW();
    map<int, int> m;
    auto sub = gettimeW() - cur;
    printf("map create: custrom %ld \n", sub);
    cur = gettimeW();
    unordered_map<int, int> um;
    sub = gettimeW() - cur;
    printf("unmap init: custrom %ld \n", sub);
    cur = gettimeW();
    // 初始化
    for (int i = 0; i < size; i++)
    {
        m[i] = i;


    }
    sub = gettimeW() - cur;
    printf("map init: custrom%ld \n", sub);
    cur = gettimeW();
    for (int i = 0; i < size; i++)
    {
        um[i] = i;
    }
    sub = gettimeW() - cur;
    printf("unmap init: custrom%d \n", sub);

    // map的查找
    {
        int count = 0;
        auto cur = time(nullptr);
        for (int i = 0; i < times; i++)
        {
            for (int j = 0; j < size; j++)
            {
                if (m.find(j) != m.end())
                {
                    count++;
                }
            }
        }
        auto sub = time(nullptr) - cur;
        printf("map count: %d, custrom%d \n", count, sub);

    }


    // unordered_map的查找
    {
        int count = 0;
        auto cur = time(nullptr);
        for (int i = 0; i < times; i++)
        {
            for (int j = 0; j < size; j++)
            {
                if (um.find(j) != um.end())
                {
                    count++;
                }
            }
        }
        auto sub = time(nullptr) - cur;
        printf("ordermap count: %d, custrom%d \n", count, sub);

    }


}


void testMapMem(int size)
{
    map<int, int> m;



    // 初始化
    for (int i = 0; i < size; i++)
    {
        m[i * 2] = i;


    }

    int count = 0;
    for (int j = 0; j < size; j++)
    {
        if (m.find(j) != m.end())
        {
            count++;
        }
    }
    getchar();
}

void testUnorderMapMem(int size)
{

    unordered_map<int, int> um;


    // 初始化
    for (int i = 0; i < size; i++)
    {

        um[i * 2] = i;

    }

    int count = 0;
    for (int j = 0; j < size; j++)
    {
        if (um.find(j) != um.end())
        {
            count++;
        }
    }
    getchar();
}

typedef function<void(int, int)> bindc11;

int main()
{
    bindc11 t;

    printf("size; %d \n", sizeof(t));
//    test(10,50000000);        // 容量:10        查找:1千万轮次

//    test(100, 1000000);        // 容量:100        查找:1百万轮次
//
    test(10000, 100000);        // 容量:1000        查找:10万轮次
//
//    test(10000, 10000);        // 容量:10000    查找:1万轮次
//
//    test(100000, 1000);        // 容量:100000    查找:1000轮次
//
//    test(1000000, 100);        // 容量:1000000    查找:100轮次
//
//    test(10000000, 10);        // 容量:10000000    查找:10轮次

//    testMapMem(100000);
//    testUnorderMapMem(100000);
//    getchar();

    return 0;
}


release模式参照上面

但是debug模式下,

4.8.5编译器结果  map 100 以下更快其他, unordermap 更快

8.0的任何大小的容器都是 unordermap快

创建和初始化对比

100个元素的时候

map create: custrom 2082 
unmap init: custrom 68 
map init: custrom69716 
unmap init: custrom36615 

1000个元素

map create: custrom 1678 
unmap init: custrom 92 
map init: custrom942322 
unmap init: custrom361346 

10000个元素

map create: custrom 1275 
unmap init: custrom 172 
map init: custrom6359164 
unmap init: custrom3515528 

100000个元素

map create: custrom 1214 
unmap init: custrom 67 
map init: custrom75028499 
unmap init: custrom26605541 

消耗时间map都大于unorder_map

内存测试 8 编译器 ,大小100 - 1000 的时候都一样

10000   上面是map, 下面是undorder_map

100000

 

 

 1000000

 

 10000000 

与map对比
map

优点:

 有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作;

 红黑树,内部实现一个红黑树使得map的很多操作在O(lgn)的时间复杂度下就可以实现,因此效率非常的高。

缺点:空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间

应用场景:对于那些有顺序要求的问题,用map会更高效一些

unordered_map

优点:因为内部实现了哈希表,因此其查找速度非常的快
缺点:哈希表的建立比较耗费时间
应用场景:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结

内存占有率的问题就转化成红黑树 VS Hash表,还是unordered_map占用的内存要高;
但是unordered_map执行效率要比map高很多;
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的。

unordered_map扩容原理

unordered_map 内部实现是散列表,是一个无序的容器。内部实现的散列表采用了链地址法,意思是使用链表来解决散列冲突。当往容器中加入一个元素的时候,会计算散列值,然后取余之后放到一个桶 (bucket) 里。如果不断往容器加元素,那么所有的桶都会变成一个很长的链表,这样效率就很低了,这种情况应该如何避免呢?unordered_map 采用了扩容的机制,当负载因子 (load factor) 超过了阈值,就会进行一次扩容。负载因子的计算方法是总键值对数除以桶数。扩容的时候,会重新计算散列,重新放入到桶里。

还要评估: 创建耗时和再扩容

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值