第六章#6.3查找 之 散列表的查找

散列:记录的存储位置和关键字之间存在对应的关系

对应关系——hash函数

Loc(i)=H(keyi)

就是对应根据关键字的值,用某个函数计算后得到它的位置

Hash哈希:单词翻译为散列、杂凑,所以这就是散列表

根据散列函数H(key)=k

可以直接查找key=9,则访问H(9)=9号地址,若内容为9则成功;若查不到,则返回一个特殊值,如空指针或空记录

  • 优点:查找效率非常高,O(1)

  • 缺点:空间效率低

散列方法(杂凑法):选取某个函数,根据关键字直接计算存储位置,并按此存放;查找时,由同一个函数对给定值k计算地址,将k与地址单元中元素关键码进行比,确定查找是否成功

散列函数(杂凑函数):散列方法中使用的转换函数

散列表:用散列函数构造的表就是散列表

冲突:不同的关键字通过散列函数计算的地址相同;在散列查找方法中冲突不可避免,只能尽可能减少

同义词:具有相同函数值的多个关键字

###散列函数的构造方法###

考虑因素:

  • 执行速度,函数要比较见到

  • 关键字的长度

  • 散列表的大小,太小冲突多,太大浪费空间

  • 关键字分布情况

  • 查找频率

根据集合特征:

  • 要求一:哈希表是用空间换查找时间,但是还是要求地址空间尽量小

  • 要求二:无论什么方法存储,目的都是尽量均匀存放元素,以避免冲突

方法:

  • 直接定址法

  • 除留余数法

  • 数字分析法

  • 平方取中法

  • 折叠法

  • 随机数法

方法一:直接定址法

Hash(key)=a·key+b (a、b是常数)

优点:以关键码key的某一个线性函数值作为散列地址,不会产生冲突(线性函数的自变量和因变量是一一对应的,不会产生冲突)

缺点:要占用连续的地址空间,空间效率较低

方法二:除留余数法(较好)

Hash(key)=key mod p (p是一个整数)

关键 如何取合适的p

技巧 设表长为m,取p≤m 且为 质数

###散列表的查找###

处理冲突的方法

包括:开放定址法(开地址法)、链地址法(拉链法)、再散列法(双散列函数法)、建立一个公共溢出区

其中前两种方法较为常见,接下来着重介绍

方法一:开放定址法(开地址法)

有冲突时就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能被找到,并将数据元素存入

线性探测法

增量di是一个线性递增的序列,+1,+2,...,直到有空位置就存进去

查找的时候,利用哈希函数找到对应位置比对是不是,不是就,+1,+2,...,直到找到为止,如果到空的位置还没有找到,那说明序列不含有这个关键字,这是显然的,如果含有这个关键字,那么按照线性试探的方法一定会找到

二次探测法

查找的时候类似线性探测,先利用哈希函数计算位置,然后去找,没找到就加上二次规律的增量di再去找,直到找到或者当前位置是空为止

伪随机数法

di是一个伪随机数

计算机不会产生绝对的随机数,只能够产生伪随机数,绝对随机数是一种理想的随机数,这里的伪随机数就是计算机产生的随机的但又具有一定规律的数,它一部分遵循规律,一部分不遵循规律

不推荐这种方法~

方法二:链地址法(拉链法)

具有相同地址的记录成一个单链表

m个散列地址就设m个单链表,然后用数组将m个单链表的表头指针储存起来,形成一个动态结构

链地址法建立散列表步骤:

  • step1:取数据元素的关键字key,计算其散列函数值(地址)。若该地址对应的链表为空,则将该元素插入此链表;否则执行Step2解决冲突

  • step2:根据选择的冲突处理方法,计算关键字key的下一个存储地址若该地址对应的链表为不为空,则利用链表的前插法或后插法将该元素插入此链表

链地址法的优点:

  • 无“聚集”现象:非同义词不会冲突

  • 链表上结点空间动态申请,更适合于表长不确定的情况

散列表的查找及效率分析

 

几点结论

  • 散列表,即哈希表技术具有很好的平均性能,优于一些传统的技术,甚至比二分查找法还优秀

  • 链地址法优于开地址法,这是显然的,它对于冲突的解决明显更加优秀

  • 除留余数法作散列函数优于其他类型函数,取小于等于关键字表表长的质数,可以获得比较好的散列效果


除此之外在文章结尾我还推荐学习STL中的hash_table和hash_map方便对知识点的运用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值