就内存使用而言,C ++中的map和unordered_map有什么区别?

时间:2019-06-04 06:51:30

标签: c++ dictionary stl

我正在解决InterviewBit上的一个问题,遇到一个问题, 这是链接https://www.interviewbit.com/problems/diffk-ii/。 当我使用c ++ STL映射解决此问题时,它向我显示消息

超出内存限制。您的提交未在分配的内存限制内完成。 这是我的代码

int Solution::diffPossible(const vector<int> &A, int B) {
    int n = A.size();
    map< int , int > mp;
    for(int i =0;i<n; i++)
        mp[A[i]] = i;
    int k = B;
    for(int i =0; i<n; i++){
        if(mp.find(A[i]+k) != mp.end() && mp[A[i]+k] != i){
            return 1;
        }
        if(mp.find(A[i]-k) != mp.end() && mp[A[i]-k] != i){
            return 1;
        }
    }

    return 0;
}

,当我将地图替换为unorderd_map解决方案时,就可以接受。 这是代码

int Solution::diffPossible(const vector<int> &A, int B) {
    int n = A.size();
    unordered_map< int , int > mp;
    for(int i =0;i<n; i++)
        mp[A[i]] = i;
    int k = B;
    for(int i =0; i<n; i++){
        if(mp.find(A[i]+k) != mp.end() && mp[A[i]+k] != i){
            return 1;
        }
        if(mp.find(A[i]-k) != mp.end() && mp[A[i]-k] != i){
            return 1;
        }
    }

    return 0;
}

这意味着map比unordered_map占用更多的内存。 谁能解释这是怎么回事?为什么地图占用更多内存 比unordered_map还宽敞?

2 个答案:

答案 0 :(得分:-1)

  1. 地图被实现为二分搜索树,并且每个节点(除有用数据外)通常存储 3个指针(指向左孩子,右孩子和父母)。

  2. 无序映射被实现为哈希表,其中每个节点都在链接列表中。如果是单链接列表(属于相关存储桶),则每个节点只有 1个指针更新:但是,每个存储桶也有一个附加的指针。在没有冲突的理想情况下,内存中每个元素将有 2个指针

请注意,两个int通常将占用8个字节,与单个指针相同。


例如,查看GNU libstdc ++实现。 RB树的节点定义如下:

struct _Rb_tree_node_base
{
  typedef _Rb_tree_node_base* _Base_ptr;
  typedef const _Rb_tree_node_base* _Const_Base_ptr;

  _Rb_tree_color    _M_color;
  _Base_ptr     _M_parent;
  _Base_ptr     _M_left;
  _Base_ptr     _M_right;
  ...

在那里,您可以观察到这三个指针。


通常,很难说哪个容器消耗的总内存更少。但是,我创建了一个基准测试,将1M随机数插入两个容器中,并测量了最大居民大小(MaxRSS),以反映所有消耗的内存空间,包括堆内部数据。结果如下:

  1. 48,344 kB 对于std::map
  2. 对于std::unordered_map
  3. 50 888 kB
  4. 40,932 kB ,用于std::unordered_mapreserve

请注意,由于存储区列表的重新分配,无序映射(广告2)的内存消耗较高。这就是reserve成员函数的作用。如果一个人在乎内存消耗并事先知道元素的数量,那么他/她应该始终进行预分配(这与向量的情况相同)。

答案 1 :(得分:-3)

地图基本上是二叉搜索树,而unordered_map被实现为哈希地图。如果您看一下两者的实现,您都会很快注意到BST更大。

这也意味着地图比unordered_map慢得多。

                | map             | unordered_map
---------------------------------------------------------
Ordering        | increasing  order   | no ordering
                | (by default)        |

Implementation  | Self balancing BST  | Hash Table
                | like Red-Black Tree |  

search time     | log(n)              | O(1) -> Average 
                |                     | O(n) -> Worst Case

Insertion time  | log(n) + Rebalance  | Same as search

Deletion time   | log(n) + Rebalance  | Same as search

BST:

struct node
{
    int data;
    node* left;
    node* right;
};

HashMap:

struct hash_node {
    int key;
    int value;
    hash_node* next;
}

参考:https://www.geeksforgeeks.org/map-vs-unordered_map-c/