C ++中的map与hash_map
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C ++中的map与hash_map相关的知识,希望对你有一定的参考价值。
我在C ++中有hash_map
和map
的问题。据我所知,map
属于STL,但hash_map
不是标准。这两者有什么区别?
它们以非常不同的方式实现。
hash_map
(TR1和Boost中的unordered_map
;使用它们)使用哈希表,其中密钥被散列到表中的一个槽中,并且值存储在与该键相关联的列表中。
map
实现为平衡二叉搜索树(通常是红/黑树)。
unordered_map
应该为访问集合的已知元素提供稍好的性能,但map
将具有其他有用的特征(例如,它以排序顺序存储,允许从开始到结束遍历)。 unordered_map
在插入和删除方面比map
更快。
hash_map
是许多库实现提供的通用扩展。这正是为什么在将它作为TR1的一部分添加到C ++标准时将其重命名为unordered_map
的原因。 map通常使用平衡的二叉树(如红黑树)实现(当然实现方式不同)。 hash_map
和unordered_map
通常使用哈希表实现。因此不保持订单。 unordered_map
插入/删除/查询将是O(1)(常量时间),其中map将是O(log n),其中n是数据结构中的项目数。所以unordered_map
更快,如果你不关心项目的顺序应该优先于map
。有时你想维持秩序(按键排序),因为map
将是你的选择。
一些关键差异在于复杂性要求。
map
需要O(log(N))
时间进行插入和查找操作,因为它实现为红黑树数据结构。unordered_map
需要O(1)
的'平均'时间用于插入和发现,但允许qzxswpoi的最坏情况时间。这是因为它是使用哈希表数据结构实现的。
因此,通常,O(N)
会更快,但根据您存储的密钥和哈希函数,可能会变得更糟。
C ++规范没有说明您必须为STL容器使用什么算法。但是,它确实对它们的性能施加了某些限制,这排除了对unordered_map
和其他关联容器使用哈希表的限制。 (它们最常用红色/黑色树实现。)这些约束要求这些容器的最坏情况性能比哈希表所能提供的要好。
然而,许多人确实想要哈希表,因此基于哈希的STL关联容器多年来一直是常见的扩展。因此,他们将map
等添加到C ++标准的更高版本中。
unordered_map
是从map
(通常是balanced binary search tree
)实现的,因为rb_tree
中的所有成员都被排序,因此是map;
balanced binary search tree
是从hash_map
实施的。由于hashtable
的所有成员都没有被排除,所以hashtable
的成员没有排序。
hash_map(unordered_map)
不是c ++标准库,但现在它重命名为hash_map
(您可以将其重命名)并成为c ++标准库,因为c ++ 11更多细节请参阅unordered_map
这个问题。
下面我将从两个类型映射的实现源代码中给出一些核心接口。
map:
下面的代码只是为了表明,map只是Difference between hash_map and unordered_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
在下面的代码中,我将给出的主要部分,然后给出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
下图显示当hash_map有53个桶并插入一些值时,它是内部结构。
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);
};
};
下图显示了map和hash_map(unordered_map)之间的一些区别,图像来自:
How to choose between map and unordered_map?
我不知道是什么给出了,但是,hash_map需要20多秒才能清除()150K无符号整数键和浮点值。我正在跑步并阅读其他人的代码。
这是它包含hash_map的方式。
我在这里读到这个#include "StdAfx.h"
#include <hash_map>
说clear()是O(N)的顺序。对我来说,这很奇怪,但是,就是这样。
以上是关于C ++中的map与hash_map的主要内容,如果未能解决你的问题,请参考以下文章