C+中的映射与hash#u映射+; 在C++中,我有一个问题,涉及代码< HASHMAP> 和 MAP>代码>。我知道map在STL中,但hash\u map不是标准。两者之间有什么区别?< P> C++的规范没有确切地告诉你必须使用什么算法来为STL容器使用。但是,它确实对它们的性能施加了某些限制,这就排除了对map和其他关联容器使用哈希表的可能性。(它们最常用红/黑树实现)这些约束要求这些容器具有比哈希表更好的最坏情况性能

C+中的映射与hash#u映射+; 在C++中,我有一个问题,涉及代码< HASHMAP> 和 MAP>代码>。我知道map在STL中,但hash\u map不是标准。两者之间有什么区别?< P> C++的规范没有确切地告诉你必须使用什么算法来为STL容器使用。但是,它确实对它们的性能施加了某些限制,这就排除了对map和其他关联容器使用哈希表的可能性。(它们最常用红/黑树实现)这些约束要求这些容器具有比哈希表更好的最坏情况性能,c++,map,hashmap,C++,Map,Hashmap,然而,许多人确实想要哈希表,因此基于哈希的STL关联容器多年来一直是一种常见的扩展。因此,他们添加了无序的映射> /COD>以及以后的C++标准版本。 < P>它们以非常不同的方式实现。 hash_-map(unordered_-map在TR1和Boost中;改用它们)使用一个哈希表,其中键被哈希到表中的一个插槽,值存储在与该键绑定的列表中 map被实现为一个平衡的二叉搜索树(通常是红/黑树) unordered_映射在访问集合的已知元素时应提供稍好的性能,但map将具有其他有用的特性(例如,它

然而,许多人确实想要哈希表,因此基于哈希的STL关联容器多年来一直是一种常见的扩展。因此,他们添加了<代码>无序的映射> /COD>以及以后的C++标准版本。

< P>它们以非常不同的方式实现。
hash_-map
unordered_-map
在TR1和Boost中;改用它们)使用一个哈希表,其中键被哈希到表中的一个插槽,值存储在与该键绑定的列表中


map
被实现为一个平衡的二叉搜索树(通常是红/黑树)


unordered_映射
在访问集合的已知元素时应提供稍好的性能,但
map
将具有其他有用的特性(例如,它以排序顺序存储,允许从头到尾遍历)<代码>无序映射在插入和删除时比
映射
更快
哈希映射
是许多库实现提供的常见扩展。这就是为什么当它被添加到C++标准中作为Tr1的一部分时,它被重命名为<代码> unordeDeMAP < /C>。map通常是用一个平衡的二叉树来实现的,比如红黑树(实现当然会有所不同)<代码>哈希映射和
无序映射
通常通过哈希表实现。因此,秩序无法维持<代码>无序映射插入/删除/查询将是O(1)(恒定时间),其中映射将是O(logn),其中n是数据结构中的项数。因此,
unordered_map
速度更快,如果您不关心项目的顺序,则应优先选择
map
。有时,您需要维护顺序(按键排序),为此,
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
    需要
    O(log(N))
    插入和查找操作的时间,因为它实现为一个红黑树数据结构

  • 无序映射
    要求插入和查找的“平均”时间为
    O(1)
    ,但允许最坏情况时间为
    O(N)
    。这是因为它是使用哈希表数据结构实现的


因此,通常,
无序映射会更快,但取决于键和存储的哈希函数,可能会变得更糟。

我不知道会有什么结果,但是,哈希映射需要20秒以上的时间才能清除()150K无符号整数键和浮点值。我只是在运行和阅读其他人的代码

这就是它包含哈希映射的方式

#include "StdAfx.h"
#include <hash_map>
#包括“StdAfx.h”
#包括
我在这里读到的


表示clear()是O(N)的顺序。这对我来说很奇怪,但事实就是这样。

map
是从
平衡二叉搜索树
(通常是
rb_树
)实现的,因为
平衡二叉搜索树
中的所有成员都是按map>排序的

哈希映射
是从
哈希表
实现的。由于
哈希表
中的所有成员都未排序,因此
哈希映射(无序映射)
中的成员未排序

<代码> HasyMava不是C++标准库,但现在它改名为<代码> unordeDeMalp>/Cuff>(可以考虑重命名),成为C++标准库,因为C++ 11更详细地查看了这个问题。p> 下面我将从源代码中给出一些核心接口,说明如何实现两种类型的映射

地图: 下面的代码只是为了说明,map只是一个
平衡二叉搜索树
的包装器,它几乎所有的函数都只是调用
平衡二叉搜索树
函数

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);
};
map的
一样,惟一的成员是
rb_树
hash_映射的
惟一成员是
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);
        };

};
模板
类哈希映射{
私人:
typedef哈希表ht;
//成员数据是哈希表
ht代表;
公众:
//默认情况下为100个桶
//它可能不是100(在这里只是为了简化)
hash_-map():rep(100){};
//像上面的map的insert函数一样,只需调用rb_树的unique函数
//hash_映射,insert函数只调用hashtable的惟一insert函数
标准::对插入(常量值和v){
返回t.insert_unique(v);
};
};
下图显示了当一个hash_映射有53个bucket并插入一些值时,它的内部结构

下图显示了映射和散列映射(无序映射)之间的一些差异,该图像来自:


它实际上是在TR1中添加的(std::TR1::unordered_map),而不是C++0xI认为
map
的原因通常是由于使用
operator@kts:任何STL实现是否实际使用B树?从技术上讲,所有二进制搜索树都是B树(1-2树)。话虽如此,我不知道有哪个STL使用红色以外的任何东西/black@bk1e“适当的”B-树在数据库中特别有用,因为您希望“胖”树节点与磁盘页面对齐。OTOH,这在“普通”程序中使用的“平面”内存模型中不是很有用-所有STL