数据结构 | 哈希表与哈希冲突的解决(一)

目录

 一,哈希表的定义

二,哈希表的常用函数

三,哈希表的适用题目

四,哈希冲突

五,哈希冲突的解决方法


 一,哈希表的定义

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

——百度百科

哈希表能够根据关键字快速定位到具体的值,通常用来提高算法效率。

构造函数:

unordered_map ( size_type n = N,const hasher& hf = hasher(),const key_equal& eql = key_equal(),const allocator_type& alloc = allocator_type() );  

哈希表的构造方法:

  • 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。(常用)
  • 数字分析法:选择不容易发生冲突的部分进行哈希表构造。(如:学号后半部分)
  • 平方取中法:当无法确定关键字里的哪里分布相对均匀时,可以先求出关键字的平方值,然后按需要取平方值的中间几位作为散列地址。(这是由于平方之后中间几个值和关键字的每一位都相关,所以不同关键字更容易产生不同的地址)
  • 取随机数法:使用一个随机函数,取关键字的随机值作为散列地址。(常用于关键字长度不同的场景)
  • 除留取余法:取关键字被某个不大于散列表表长 n 的数 m 除后所得的余数 p 为散列地址。这种方式也可以在用过其他方法后再使用。(对 m 的选择很重要,一般取素数或者直接用 n。)

二,哈希表的常用函数

hash.begin():指向容器内第一个元素的迭代器。

hash.end():指向容器内最后一个元素的后一个位置的迭代器。

hash.find():可以通过key查找一个元素,返回的是迭代器类型。

hash.bucket():以key值寻找元素在容器中的位置。

hash.clear():删除容器内所有元素。

hash.count():某个key值对应的map(value)值的数量。(注:哈希表是不允许存在重复元素的,所以返回的值总是0或是1)

hash.empty():判断哈希表是否为空,如为空则为真,返回的是bool值。

hash.erase():可以删除哈希表中指定位置的元素。

hash.insert():能够向哈希表的指定位置插入元素。

hash.size():返回的是哈希表的元素个数。

hash.swap():交换两个哈希表的内容,其类型必须一致,但大小可以不同。

三,哈希表的适用题目

1.判断数组内是否有重复数字出现

2.求数组交集

3.两数之和

4....

四,哈希冲突

哈希表可能产生冲突的原因:有时不同的 Key关键字通过哈希函数可能会得到相同的地址,在操作时可能会对数据造成覆盖、丢失。之所以产生冲突是由于哈希函数有时对不同的 Key 计算之后获得了相同的地址。

五,哈希冲突的解决方法

常用的解决哈希冲突的方法有:

  • 开放定址法:在根据关键字查找哈希之后,如果发现这个地址已经有值了,就不能放在这个地址,否则会覆盖掉之前的映射。可以对计算出来的地址进行一个探测再哈希,比如往后移动一个地址,如果该地址空着就可以使用;如果超过容器最大长度,则可以对总长度取余。这里移动的地址是产生冲突时的增列序量。
  • 再散列函数法:如果产生哈希冲突后,可以使用关键字的其他部分继续计算,如果还是有冲突,则继续使用其他部分再计算地址。改方法的缺点则是效率较低,时间较长。
  • 链地址法:对关键字重复的哈希地址,来做一个链表。在很多高级语言的实现当中,都是使用这种方式处理冲突。
  • 建立一个公共溢出区:是建立一个公共溢出区,当产生哈希冲突时,把新的地址放在公共溢出区里。

个人整理学习用,欢迎讨论与修正。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值