数据结构笔记6 散列查找

散列表

目前已知的查找方法:

在这里插入图片描述
但是上述这几种方法对于长字符串的动态查找效果都不是很好。看下面的例子:
在这里插入图片描述
可以看到二分法在这个问题中效果不是很好。那么如何快速搜索到需要的关键词?如果关键词不方便比较怎么办?

查找的本质:已知对象找位置

  • 有序安排对象(将对象排列有序再查找):完全有序(二分查找,从小到大排好),半序(某些关键词中存在次序,比如查找树,某些节点的根节点比左边节点小,比右边节点大)
  • 直接算出对象的位置:散列

散列查找法的两项基本工作:

  • 计算位置: 构造散列函数确定关键词存储位置,对每个对象设计一个映射的整数值,整数值代表对象要放的位置
  • 解决冲突:应用某种策略解决多个关键词位置相同的问题。即解决比如两个对象映射后放在同一个位置的问题
    时间复杂度:几乎是O(1),与规模无关

散列表(哈希表)

表名,对象集,操作集如下
在这里插入图片描述
举例如下:
在这里插入图片描述

对于这个问题,用散列表来管理。将散列函数h选取为求余。TableSize=17,即将这些数字放到下标为0-16的表中。比如放34的时候,34对17求余,余数为0,h(34)=0,那么34放到0号位。
如果有35,h(35)=h(18)=1,冲突,此时要解决这一冲突。

将元素放好之后进行查找,如果要查找的key值是22,h(22)=5,就去表中5号位看是否存有值,如果没有,就说明22不在表中。

装填因子
在这里插入图片描述
又有如下例子:
在这里插入图片描述

这次要存放长字符串,为了减少冲突采用二维数组,每个单词先放到对应行的第一列,如果有冲突就放到第二列。

针对这个例子如何设计散列函数h(key)

一种简单的方法,看每个单词第一个字符,如果是a就放第一个位置,是b就放第二个,即:
h(key)=key[0]-‘a’
因为一共26个字母,所以根据该散列函数,设计数组规模为26*2
依次放入各个元素,当放到clock时发现产生了冲突,此时下标为2的行已经放了两个元素,放满了,ctime一样,如下图
在这里插入图片描述
可以看到,如果没有发生这种冲突,总体来说其查询,插入,删除的时间复杂度都是线性的

总结散列的基本思想:
(1)以关键字key为自变量,通过一个确定的函数h(散列函数),计算出对应的函数值h(key),作为数据对象的存储地址
(2)可能有不同的关键字映射到同一个散列地址:
即h(key i)=h(key j) (i不等于j),称为冲突,需要某种冲突解决策略。

散列函数的构造方法

散列函数的设计应考虑下面两个因素
1.计算简单,以便提高转换速度
2.关键词对应的地址空间分布均匀,以尽量减少冲突

数字关键词的散列函数构造

1.直接定址法
把散列函数设计成一个线性函数,取关键词的某个线性函数值作为散列地址,即
h(key)=a*key+b (a、b均为常数)

例如下图中h(key)=key-1990
在这里插入图片描述
2.除留余数法
散列函数为:h(key)=key mod p

在这里插入图片描述

3.数字分析法
分析数字关键字在各位上的变化情况,取比较随机的位作为散列地址
如下面例子中,手机号码一般前几位都差不多,变化最大的是后四位,所以按如下方法选取
在这里插入图片描述
在这里插入图片描述

又如在身份证号码中,每一位都有特殊含义,对18位分析,得到第6,10,14,16,17这五位相对随机分布。所以把每个号码的这五位组合在一起组成一个数。具体按下图选取h(key)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值