C++hash_map原理介绍

已经存在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

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值