CC43.【C++ Cont】哈希表的简介

目录

1.定义

核心思想:关键字→映射关系→存储地址

2.哈希函数定义

3.哈希冲突

定义

4.设计哈希函数的常用方法

1.直接定址法

2.除留余数法

5.处理哈希冲突的常用方法

1.线性探测法

注意事项

2.链地址法


1.定义

哈希表(hash table),又称散列表,可根据关键字直接进行访问,由此看出访问速度

关键字:可以理解为向哈希表中存储的数据

原理:哈希表建立了一种关键字和存储地址之间的直接映射关系,使每个关键字与结构中的唯一存储位置相对应

核心思想:关键字→映射关系→存储地址

由于哈希表可根据关键字直接进行访问,因此在理想情况下,查找的时间复杂度为O(1)

之前在C31.【C++ Cont】静态实现单链表文章中提到过哈希表的思想,可以去回顾回顾,这里节选一部分内容:

如果使用标记数组mp优化(哈希表),直接return mp[x],时间复杂度O(1)

即关键字x→映射关系mp[ ]→存储地址&mp[x]→访问*(&mp[x]) 

2.哈希函数定义

将关键字映射成对应的地址的函数(即映射关系),哈希函数又称散列函数

用公式可以表示为Hash(key) == Address

3.哈希冲突

定义

哈希函数可能会把两个或两个以上的不同关键字映射到同一地址,哈希冲突又称散列冲突

起冲突的关键字被称为同义词

例如:统计数组arr中每个数字出现的次数,arr={1,45,1e10+7,3,17}

方法1: 创建一个有1e10+17个元素的数组mp

按照C31.【C++ Cont】静态实现单链表文章的思想去创建数组mp,对于数字x其出现的次数为mp[x],显然数组的空间过大,容易导致栈溢出,不建议使用

方法2:设计一个哈希函数hash(key)==key/7

设计一个数组mp,对于数字x其出现的次数为mp[x/7]

1/7==1

45/7==3

1e10+7/7==4

3/7==3

17/7==3

显然会有哈希冲突因为45/7、3/7和17/7的结果都是3,会映射到同一地址

解决方法:比如/11或者/其他数,但可能根据数组的数字的不同,还会导致哈希冲突,因此哈希冲突不可避免,则需要1.设计一个合适的哈希函数来尽量减少冲突 2.如果有冲突要能有效解决

4.设计哈希函数的常用方法

1.直接定址法

直接取关键字的某个线性函数来计算,例如hash(key)=key或hash(key)=key-c(c为函数)

缺点:若关键字分布不连续,则会造成存储空间的浪费(见上方的例子)

直接定址法适合关键字连续的情况

2.除留余数法

比如hash(key)==key%7,即hash(key)==key%m,要选取一个合适的模数m

选取模数的方法: 取不太接近2的整数次幂的一个质数(竞赛中知道怎么用就行,无需深究原理)

5.处理哈希冲突的常用方法

1.线性探测法

从发生冲突的位置开始依次线性向后探测,直到寻找到下一个没有存储数据的位置为止,如果走到
哈希表尾,那么回绕到哈希表头的位置

例如数组arr={19,30,5,36,13,20,21},哈希函数为hash(key)==key%11,使在key%11的位置存储key,即数组mp[key%11]=key

计算key%11

19%11==8

30%11==8

5%11==5

36%11==3

13%11==2

20%11==9

21%11==10

在key%11的位置存储key的前提:这个位置之前没有存储过任何数字,那就要为这个位置赋一个都取不到的数:INF(infinite 无穷大),如下图

(这里为了演示方便,创建数组mp的大小和数组arr的大小差不多)

hash(19)==8,因此

hash(30)==8,发现mp[8]的位置放过了,因此使用线性探测法:从发生冲突的位置开始依次线性向后探测,直到寻找到下一个没有存储数据的位置为止,发现mp[9]没有存数,因此mp[9]=30

hash(5)==5,hash(36)==3,hash(13)==2因此

hash(20)==9,发现mp[9]的位置放过了,使用线性探测法,发现mp[10]没有存储数字

hash(21)==10, 发现mp[10]的位置放过了,使用线性探测法,走到哈希表尾,那么回绕到哈希表头的位置,存在mp[0]处

注意事项

一般创建的大小是原大小的两倍,防止存储过于密集,线性探测消耗的时间过多 

2.链地址法

链地址法中所有的数据不再直接存储在哈希表中,哈希表中存储指针,若没有数据映射这个位置
时,指针为空(访问空指针指向的数据是非法的);若有多个数据映射到这个位置时,则把这些冲突的数据链接成一个链表,"挂"在哈希表这个位置下面

例如:例如数组arr={19,30,5,36,13,20,21,12,24,96},哈希函数为hash(key)==key%11

初始状态下元素都为空指针

若有多个数据映射到这个位置时,则执行链表头插(类似带哨兵位的链表),最终结果为:

缺点:如果所有的数都挂到mp的同一个下标,则查找这些数的时间复杂度为O(N),解决方法:使用红黑树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangcoder

赠人玫瑰手有余香,感谢支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值