我在C ++中遇到hash_map
和map
的问题。我知道map
在STL中,但hash_map
不是标准。这两者有什么区别?
答案 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_map
和unordered_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_map
从hashtable
开始实施。由于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_map
从hashtable
实现,其结构有点像这样:
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个存储桶并插入一些值时,它是内部结构。
答案 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)的顺序。对我而言,这很奇怪,但是,就是这样。