hash table是一个非常重要的数据结构,但目前版本的stl中并没有,C++11中会加入.目前版本的trl中有一个std::tr1::unordered_map, 需要include <tr1/unordered_map> 本文以这个实现为准.
一,hash与map
hash与map很像(从名字也看得出来: unordered_map vs map),包括各种操作的api和应用场景. hash的性能非常出色:拥有高达O(1)的插入和查找复杂度.这比map(平衡二叉树)的O(logn)要快. 当然,它的元素是无序的,但其实很多情况下不需要有序.总体来讲,hash的性能要比map快.
但hash也有hash的问题:
1,数据量不大的情况下,O(n)并不见得比O(logn)快多少,有可能还要慢
2,rehash问题, hash需要将key通过hash函数映射成size_t,再存储到一块预先申请好的连续空间上,因此当这些空间不够用了以后就需要重新分配空间并对原有元素进行重新计算&分配.这是很耗时间的. 如果能预估出所存元素的最大个数,可以用rehash或构造函数一次申请足够的空间,这样就可以避免rehash.
3,冲突,当数据量很大时不可避免地会有冲突,这会一定程度上影响hash的性能,但事实上C++已经把这个问题解决好了, 我们可以完全透明地使用.
二:性质与 常用Api函数
1,插入, 与map一样,可以用insert 或下标运算符插入,并且insert会返回一个pair<iterator,bool> 第二个值表示是否重复, 另一个版本的insert可以提供一个hint值,但这个hint好像不起作用(也可能我不知道,但无序的容器为什么要hint值呢? 或许某些实现版本中有用)
2, 查找find, 返回一个iter
3,size,max_size,bucket_count,max_bucket_count
size返回元素的个数
bucket_count,返回当前已分配空间可容纳的元素个数
通常max_size=max_bucket_count, 表示系统可以容纳的最大元素个数
4, load_factor和max_load_factor
load_factor返回hash当前的负载率
max_load_factor为参数时返回最大负载率,有参数时可以设置最大负载率
理论上负载率接近1时效率会降低,但我的测试显示不出什么差别, 原因未知~
5,rehash与clear
hash初始时仅分配11个元素的空间,,每次rehash时,会申请2n+1大小的空间,n是当前空间大小
clear只能清空元素,但并不释放空间
rehash可以减少/释放空间,每次分配比参数略大一点的空间
6,插入速度上hash确实比map快一些, 但如果能很好滴提供hint值,map插入的速度将接近hash(都是O(1))