C++STL中的hash_map 哈希表

map与hash_map

map与hash_map都是在C++STL中常用的数据结构。
map:存储数据结构是采用红黑树实现,提供了key-value的存储和查找功能,查找速度可达log(n)。
hash_map:基于hash_table(哈希表)储存,相对map来说,他的查找速度大大的降低,几乎可以看成是常熟时间;但是代价就是消耗更多的内存(但是在现在内存越来越大的情况下,用内存换时间的选择十分值得)。

他们之间的区别:

  • 构造函数:hash_map需要hash函数,比较函数(等于函数);map只需要比较函数(小于函数)。
  • 存储结构:hash_map采用hash表存储,map一般采用红黑树(RB Tree)实现。

什么时候选择hash_map和map(使用场景):

  • hash_map 查找速度会比map快,而且查找速度基本为数据数据量大小,属于常数级别。
  • map的查找速度是log(n)级别。

但这并不意味着一定常数就比log(n)小:因为在hash_map中,每一个元素的存储都需要经过hash函数转换为对应的hash值,这些都是需要时间的。
如果考虑查找效率并对内存大小没有要求,当元素达到一定数量级时,考虑hash_map。
如果要求尽可能少消耗内存,那么hash_map可能会不那么适合,特别是当hash_map对象特别多时,内存消耗就更大了,而且hash_map的构造速度也比较慢。

总的来说,权衡他们因素有三个:查找速度, 数据量, 内存使用

hash_map

hash_map需要一个hash函数和比较函数(如果不提供,在符合的情况下,STL会为我们提供缺省的函数):使用一个下标范围比较大的数组来存储元素其中的每个元素的关键字都与一个hash值(即数组下标)相对应,于是用这个数组单元来存储这个元素,这个数组单元称之为“桶。
那么如何获得hash值呢:在存储数据时,hash函数会根据数据的key值得到该数据的hash值。

但也有例外的情况:hash值和元素关键字并不一定是一一对应的,根据hash函数很可能会对不同的元素的key生成相同的hash值,从而把不同的元素放在了相同的“桶”,这种情况称之为“冲突”。因此哈希表有“直接定址”与“解决冲突”两个特点。

hash_map会在一开始分配一大片内存,形成许多“桶”。在之后插入元素时,根据以下步骤:

  1. 获取元素的key值
  2. 根据key值通过hash函数得到hash值
  3. 得到该hash值的“桶”号
  4. 将元素(key和value)存放在“桶”中

而查找元素的步骤为:

  1. 获得key值
  2. 根据key值通过hash函数得到hash值
  3. 得到相应的“桶”号
  4. 比较桶内元素是否与key值相同
  5. (若存在该key对应的数据)取出该key的value

使用hash_map

#include<hash_map>
//细节省略......
hash_map<string, int> hashmap;
//STL会为我们缺省的提供hash函数与比较函数
//该声明等同于hash_map<string, int, hash<string>, equal_to<int> > mymap;

C++支持的提供缺省hash函数对应的数据类型有:char*,const char*,char,unsigned char,signed char,short,unsigned short,int ,unsigned int,long ,unsigned long
也就是说,以上的数据类型,STL会为我们提供缺省的hash函数;而对于其他的数据类型,我们需要自己提供(例如string):

自定义hash函数

struct MyHash{
        size_t operator()(const string& str) const
        {
                unsigned long hash_value = 0;
                for (size_t i = 0 ; i < str.size() ; i ++)
                hash_value= 5*hash_value+ str[i];
                return size_t(hash_value);
        }
};

声明自己的hash函数需要遵循以下几点:

  1. 使用strut ,并重载operator()
  2. 返回 size_t
  3. 形参需要为hash的key的数据类型
  4. const函数

写出了自己的hash函数,上面的hash_map声明需要改为:

hash_map<string, int , MyHash> hashmap;

接下来写比较函数:

自定义比较函数

在hash_map中,要比较桶内的数据和key是否相等 。
假如我们存储的是一个自定义数据类型:
第一种设计比较函数的方法,就是重载==操作符,使用equal_to比较:

struct stu{
	int ID;
	int data;
	//重载==
	bool operator == (const stu & Temp){
		return ((ID==Temp.ID)&&(data==Temp.data));
	}
};

重载了stu数据结构的==之后,使用equal_to

hash_map<string, stu, MyHash,equal_to<stu>> hashmap;

equal_to的定义:
template <class _Tp>
struct equal_to : public binary_function<_Tp,_Tp,bool>
{
bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; }
};

另一种方法,就是写一个函数对象

struct compare_func{
        bool operator()(const char* s1,const char* s2) const{
                return strcmp(s1,s2)==0;        
        }
};

在有了conpare_func之后,就可以使用hash_map了:

hash_map<const char*a,string , hash<const char*>, compare_func> StrMap;

使用typedef定义hash_map

typedef hash_map<const char*, string, hash<const char*>, compare_str> StrMap;
//..........
StrMap mymap;
mymap["ABC"]="aaaaaaa";
mymap["EFG"]="bbbbbbb";
//..........

因此如果我们想在hash_map中加入自己的数据类型,我们只需要做两件事:你只要做两件事,定义hash函数,定义比较(等于)函数

hash_map 函数

hash_map的函数和map的函数差别不大,以下为常用的函数

  1. hash_map(size_type n):为了程序运行效率,这个参数十分重要,n为hash桶的个数,个数越多,hash_map发生冲突的概率就越小,效率也越高;但相应的内存消耗会变大。
  2. const_iterator find(const key_type& k) const:用于查找,参数为key值,返回一个该参数位置的迭代器。
  3. data_type&operator[](const key_type& k ):类似map的[key]下标查找,但注意的是与map一样,若无对应key的数据,会增加一个key的元素。
  4. const_iterator find(const key& key) const:find()函数可与上一条[key]下标查找相对应,若无该key元素存在,他不会增加一个该key的元素。
  5. insert 函数:在容器中不包含key值时,insert函数和[]操作符的功能差不多,但注意的是,当元素越来越多,为了效率,程序会申请更多的内存以存放更多的桶及其元素,这时在insert后,iterator不一定依然有效。
  6. erase 函数:但在SGI STL中,erase并不会自动回收内存,因此调用erase后,其他元素的iterator还是可用的。

相关的hash容器

容器有set, multimap, multiset
hash 容器除了hash_map之外,还有hash_set, hash_multimap, has_multiset
这些容器使用起来和(set, multimap, multiset的区别)与(hash_map和map的区别)一样。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值