C ++中的map与hash_map

时间:2010-02-03 02:12:23

标签: c++ map hashmap

我在C ++中遇到hash_mapmap的问题。我知道map在STL中,但hash_map不是标准。这两者有什么区别?

6 个答案:

答案 0 :(得分:128)

它们以非常不同的方式实施。

hash_map(TR1中的unordered_map和Boost;使用这些代替)使用散列表,其中密钥被散列到表中的一个插槽,并且值存储在与该键绑定的列表中

map实现为平衡二叉搜索树(通常是红/黑树)。

unordered_map应该为访问集合的已知元素提供稍好的性能,但map将具有其他有用的特征(例如,它以排序顺序存储,允许从头到尾遍历)。插入和删除unordered_map的速度比map更快。

答案 1 :(得分:34)

hash_map是许多库实现提供的常见扩展。这正是它作为TR1的一部分被添加到C ++标准时被重命名为unordered_map的原因。 map通常使用平衡的二叉树(如红黑树)实现(当然实现方式不同)。 hash_mapunordered_map通常使用哈希表实现。因此不保持订单。 unordered_map插入/删除/查询将是O(1)(常量时间),其中map将是O(log n),其中n是数据结构中的项目数。因此unordered_map更快,如果您不关心项目的顺序,则应优先于map。有时您希望维护订单(按键排序),因此map将是您的选择。

答案 2 :(得分:13)

一些关键差异在于复杂性要求。

  • map需要O(log(N))时间进行插入和查找操作,因为它实现为红黑树数据结构。

  • unordered_map要求插入和查找的{平均'时间为O(1),但允许最差时间为O(N)。这是因为它是使用哈希表数据结构实现的。

因此,通常unordered_map会更快,但根据您存储的密钥和哈希函数,可能会变得更糟。

答案 3 :(得分:4)

C ++规范并未准确说明您必须为STL容器使用哪种算法。但是,它确实对它们的性能施加了某些限制,这排除了map和其他关联容器的哈希表的使用。 (它们最常用红色/黑色树实现。)这些约束要求这些容器的最坏情况性能比哈希表所能提供的要好。

然而,许多人确实想要哈希表,因此基于哈希的STL关联容器多年来一直是常见的扩展。因此,他们将unordered_map等添加到C ++标准的更高版本中。

答案 4 :(得分:1)

map是从balanced binary search tree(通常是rb_tree)实现的,因为balanced binary search tree中的所有成员都已排序,因此map也是如此;

hash_maphashtable开始实施。由于hashtable中的所有成员均未排序,因此hash_map(unordered_map)中的成员未进行排序。

hash_map不是c ++标准库,但是现在它已重命名为unordered_map(您可以将其重命名),并成为c ++标准库,因为c ++ 11看到了这个问题{{3} }以获取更多详细信息。

下面,我将从源代码中提供一些核心接口,说明如何实现两种类型的映射。

地图:

下面的代码只是为了说明,map只是balanced binary search tree的包装,几乎所有功能都只是调用balanced binary search tree函数。

template <typename Key, typename Value, class Compare = std::less<Key>>
class map{
    // used for rb_tree to sort
    typedef Key    key_type;

    // rb_tree node value
    typedef std::pair<key_type, value_type> value_type;

    typedef Compare key_compare;

    // as to map, Key is used for sort, Value used for store value
    typedef rb_tree<key_type, value_type, key_compare> rep_type;

    // the only member value of map (it's  rb_tree)
    rep_type t;
};

// one construct function
template<typename InputIterator>
map(InputIterator first, InputIterator last):t(Compare()){
        // use rb_tree to insert value(just insert unique value)
        t.insert_unique(first, last);
}

// insert function, just use tb_tree insert_unique function
//and only insert unique value
//rb_tree insertion time is : log(n)+rebalance
// so map's  insertion time is also : log(n)+rebalance 
typedef typename rep_type::const_iterator iterator;
std::pair<iterator, bool> insert(const value_type& v){
    return t.insert_unique(v);
};

hash_map

hash_maphashtable实现,其结构有点像这样:

Difference between hash_map and unordered_map?

在下面的代码中,我将给出hashtable的主要部分,然后给出hash_map

// used for node list
template<typename T>
struct __hashtable_node{
    T val;
    __hashtable_node* next;
};

template<typename Key, typename Value, typename HashFun>
class hashtable{
    public:
        typedef size_t   size_type;
        typedef HashFun  hasher;
        typedef Value    value_type;
        typedef Key      key_type;
    public:
        typedef __hashtable_node<value_type> node;

        // member data is buckets array(node* array)
        std::vector<node*> buckets;
        size_type num_elements;

        public:
            // insert only unique value
            std::pair<iterator, bool> insert_unique(const value_type& obj);

};

map's的成员是rb_tree,仅hash_map's的成员是hashtable。它的主要代码如下:

template<typename Key, typename Value, class HashFun = std::hash<Key>>
class hash_map{
    private:
        typedef hashtable<Key, Value, HashFun> ht;

        // member data is hash_table
        ht rep;

    public:
        // 100 buckets by default
        // it may not be 100(in this just for simplify)
        hash_map():rep(100){};

        // like the above map's insert function just invoke rb_tree unique function
        // hash_map, insert function just invoke hashtable's unique insert function
        std::pair<iterator, bool> insert(const Value& v){
                return t.insert_unique(v);
        };

};

下图显示了hash_map具有53个存储桶并插入一些值时,它是内部结构。

enter image description here

下图显示了map和hash_map(unordered_map)之间的一些区别,该图像来自enter image description here

How to choose between map and unordered_map?

答案 5 :(得分:0)

我不知道是什么给出了,但是,hash_map需要20多秒才能清除()150K无符号整数键和浮点值。我正在跑步并阅读其他人的代码。

这是它包含hash_map的方式。

#include "StdAfx.h"
#include <hash_map>

我在这里读到了这个 https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap

说clear()是O(N)的顺序。对我而言,这很奇怪,但是,就是这样。