简体   繁体   English

在内存使用方面,c ++中的map和unordered_map有什么区别吗?

[英]Is there any difference between map and unordered_map in c++ in terms of memory usage?

I am solving a problem on InterviewBit and come across a question, here's link https://www.interviewbit.com/problems/diffk-ii/ . 我在InterviewBit上解决了一个问题并遇到了一个问题,这里是链接https://www.interviewbit.com/problems/diffk-ii/ When I have used c++ STL map to solve this problem, it shows me the message 当我使用c ++ STL map来解决这个问题时,它会向我显示消息

Memory Limit Exceeded. 内存限制超出。 Your submission didn't complete in the allocated memory limit. 您的提交未在分配的内存限制中完成。 here's my code 这是我的代码

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;
}

and when I have replaced map by unorderd_map solution accepted. 当我用unorderd_map解决方案替换map时接受了。 Here's code 这是代码

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;
}

It means map is taking more memory than unordered_map. 这意味着map比unordered_map占用更多内存。 Can anyone explain how this is happening? 任何人都可以解释这是怎么回事? Why map is taking more memory space than unordered_map? 为什么map比unordered_map占用更多的内存空间?

  1. Maps are implemented as binary search trees and each node (additionally to useful data) typically stores 3 pointers (to a left child, a right child, and a parent). 映射被实现为二进制搜索树,并且每个节点(除了有用数据之外)通常存储3个指针 (对于左子节点,右子节点和父节点)。

  2. Unordered maps are implemented as hash tables , where each node is in a linked list. 无序映射实现为哈希表 ,其中每个节点都在链表中。 In case of a singly linked list (that belongs to a relevant bucket), there is only 1 pointer per node. 在单链表(属于相关桶)的情况下,每个节点只有1个指针 UPDATE : However, there is also an additional pointer for each bucket. 更新 :但是,每个存储桶还有一个额外的指针。 In an ideal case where there are no collisions, there would be 2 pointers per element stored in memory. 在没有冲突的理想情况下,每个元素存储2个指针存储在内存中。

Note that 2 int s will typically occupy 8 bytes, same as a single pointer. 注意,2个int通常占用8个字节,与单个指针相同。


For example, look at the GNU libstdc++ implementation. 例如,查看GNU libstdc ++实现。 The RB tree's node is defined as follows: 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;
  ...

There, you can observe those 3 pointers. 在那里,你可以观察到这三个指针。


Generally, it's hard to say which container will consume less overall memory. 通常,很难说哪个容器会消耗更少的总体内存。 However, I created a benchmark to insert 1M random numbers into both containers and measured maximum resident size (MaxRSS) to reflect all the consumed memory space including, eg, heap housekeeping data. 但是,我创建了一个基准,将1M随机数插入到两个容器中并测量最大驻留大小 (MaxRSS)以反映所有消耗的内存空间,包括例如堆内务数据。 The results were as follows: 结果如下:

  1. 48,344 kB for std::map , 48,344 kB for std::map
  2. 50 888 kB for std::unordered_map , 50 888 kB for std::unordered_map
  3. 40,932 kB for std::unordered_map with reserve . 40,932 kB for std::unordered_map with reserve

Note that the memory consumption for the unordered map (ad 2.) was higher due to reallocations of bucket lists. 请注意,由于存储桶列表的重新分配,无序映射(广告2)的内存消耗较高。 That is what reserve member function is for. 这就是reserve会员职能的用途。 If one cares about memory consumption and knows the number of elements beforehand, he/she should always preallocate (this is the same situation as for vectors). 如果一个人关心内存消耗并事先知道元素的数量,他/她应该总是预先分配(这与向量的情况相同)。

A map is basically a binary search tree, while unordered_map is implemented as hash map. 映射基本上是二叉搜索树,而unordered_map实现为哈希映射。 If you look at implementations of both, you'll quickly notice that a BST is quite a bit bigger. 如果你看看两者的实现,你会很快注意到BST要大得多。

It also means that map is a lot slower than unordered_map. 这也意味着map比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: BST:

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

HashMap: HashMap的:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM