已经存在map了,为什么还要使用hash_map?
答:map内部自建一颗红黑树,具有对数据自动排序的功能,查询效率也是很高,时间复杂度是O(logN),但如果需要频繁的查询,比较的次数多也会成为瓶颈。那有没有办法能够使比较次数降到一到两次呢,hash_map就可以实现。
hash_map原理:
hash_map基于哈希表,哈希表的最大优点就是把数据的存储和查询消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比较多的内存。
其基本原理是:使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数,也叫做散列函数),使得每个元素的关键字都与一个函数值(hash值)相对应,于是用这个数组单元来存储这个元素;也可以理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所在的地方,称为桶。
但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”中。总的来说,“直接定址”与“解决冲突”是哈希表的两大特点。
hash_map,首先分配一大块内存,形成许多桶,利用hash函数,对key进行映射到不同区域(桶)进行保存。其插入过程是:
1、得到key
2、通过hash函数得到hash值
3、得到桶号(一般都为hash值对桶数求模)
4、存放key与value在桶内。
其取值过程是:
1、得到key
2、通过hash函数得到hash值
3、得到桶号
4、比较桶的内部元素是否与key相等,若不想等,则没有找到
5、取出相等记录的value。
hash_map是一个聚合类,它继承自_Hash类,包括一个vector,一个list和一个pair,其中vector用于保存桶,list用于进行冲突处理,pair用于保存key->value结构,简单的伪代码如下:
class hash_map<class _Tkey, class _Tval>
{
private:
typedef pair<_Tkey, _Tval> hash_pair;
typedef list<hash_pair> hash_list;
typedef vector<hash_list> hash_table;
};
hash_map的函数用法基本与map一致。
什么时候需要用hash_map,什么时候需要用map?
总体来说,hash_map查找速度会比map快,而且查找速度基本和数据量大小相关,属于常数级别;而map的查找速度是log(n)级别。并不一定常数就比log(n)小,hash还有hash函数的耗时。如果你考虑效率,特别是元素达到一个数量级时,考虑考虑hash_map。但若你对内存使用特别严格,希望程序尽可能少消耗内存,那么一定要小心。
选择基于三个因素:查找速度,数据量,内存使用。
gcc4.8版本上测试代码如下:
#include <iostream>
#include <ext/hash_map>
#include <ctime>
using namespace std;
using namespace __gnu_cxx;
int main()
{
hash_map<int, int> Hash_map;
Hash_map[1] = 1;
Hash_map[2] = 2;
Hash_map[3] = 3;
hash_map<int, int>::iterator iter;
for(iter = Hash_map.begin(); iter != Hash_map.end(); ++iter)
{
cout<<iter->second<<endl;
}
}
参考:
https://www.cnblogs.com/evidd/articles/8821349.html