散列表查找(哈希表)知识点
来源:互联网 发布:恒腾网络 股价 编辑:程序博客网 时间:2024/05/22 13:21
本文目录
- 定义
- 散列表查找步骤
- 使用散列表存在的问题
- 散列函数的构造方法
- 处理冲突的方法
1. 定义
相比于比较查找法,散列表的查找是通过计算来进行实现的,我们只需要通过某个函数f,使得存储位置=f(关键字),使得每个关键字key对应一个存储位置f(key)。这里我们把这种对应关系f称为散列函数,又称为哈希(Hash)函数。故采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash Table)。关键字对应的记录存储位置我们称为散列地址。
2. 散列表查找步骤
- 第一步,存储时通过散列函数计算记录的散列地址,并按此散列地址存储该记录。
- 第二步,查找时通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。
因此,散列技术既是一种存储技术,也是一种查找方法。
3. 使用散列表存在的问题
- 散列技术最适合的求解问题是查找与给定值一一对应的记录
- 散列表也不适合范围查找
- 冲突(collision):两个关键字key1不等于key2,但是却有f(key1)=f(key2),并且key1和key2称为这个散列函数的同义词(synonym)。
3. 散列函数的构造方法
构造原则
- 计算简单:散列函数的计算时间不应该超过其他查找技术与关键字比较的时间。
- 散列地址分布均匀:尽量让散列地址均匀分布在存储空间中。
经典构造方法
直接定址法
取关键字的某个线性函数值为散列地址,即: f(key)=a*key+b(a、b为常数)
比如:统计0-100岁的人口数字,可以直接使用年龄的数字作为地址。
数字分析法
采用抽取的方法,使用关键字的一部分来计算散列存储位置的方法。通常适用于处理关键字位数比较大的情况,如果事先知道关键字的分布且关键字的若干位分布较均匀,就可以考虑。
平方取中法
假设关键字是1234,那么他的平方就是1522756,再抽取中间的三位就是227,作为散列地址。平方取中法比较适合不知道关键字的分布,而位数又不是很大的情况。
折叠法
折叠法是将关键字从左到右分割成位数相等的几部分(注意最后一部分位数不够可以短些),然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。比如我们的关键字是9876543210,散列表表长为三位,我们将它分为四组,987|654|321|0,然后将他们叠加求和得1962,再求后3位得到散列地址为962,也可以从一端向另一端来回折叠后对齐相加。比如我们将987和321反转,再与654和0相加,变成1566,取566作为散列地址。
折叠法适合事先不需要知道关键字的分布,但是位数较多的情况。
除留余数法
此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为:
f(key)=key mod p (p<=m),关键在于选择合适的p。
根据经验,若散列表长为m,通常p为小于或等于表长(最好接近于m)的最小质数或不包含小于20质因子的合数。
随机数法
选择一个随机数,取关键字的随机函数值为它的散列地址。也就是f(key)=random(key)。这里random函数是随机函数,当关键字的长度不等时,采用这个方法构造散列函数是比较合适的。
如果关键字是字符串,可以转化为ASCII码或者Unicode码来处理
处理冲突的方法
开放定址法
开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
fi(key) = (f(key)+di) MOD m (di=1,2,3,……,m-1)
用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探测到开放的地址则表明表中无待查的关键字,即查找失败。
比如说,我们的关键字集合为{12,67,56,16,25,37,22,29,15,47,48,34},表长为12。 我们用散列函数f(key) = key mod 12,当计算前S个数{12,67,56,16,25}时,都是没有冲突的散列地址,直接存入:
计算key = 37时,发现f(37) = 1,此时就与25所在的位置冲突。
于是我们应用上面的公式f(37) = (f(37)+1) mod 12 = 2。于是将37存入下标为2的位置。这其实就是房子被人买了于是买下一间的作法:
到了 key=48,我们计算得到f(48) = 0,与12所在的0位置冲突了,不要紧,我们f(48) = (f(48)+1) mod 12 = 1,此时又与25所在的位置冲突。于是f(48) = (f(48)+2) mod 12=2,还是冲突……一直到 f(48) = (f(48)+6) mod 12 = 6时,才有空位,机不可失,赶快存入:
我们把这种解决冲突的开放定址法称为线性探测法。
从这个例子我们也看到,我们在解决冲突的时候,还会碰到如48和37这种本来都不是同义词却需要争夺一个地址的情况,我们称这种现象为堆积。很显然,堆积的出现,使得我们需要不断处理冲突,无论是存入还是査找效率都会大大降低。
二次探测法
fi(key) = (f(key)+di) MOD m (di = 1平方, -1平方, 2平方, -2平凡发,……, q2, -q2, q <= m/2)
我们可以改进di = 12, -12, 22, -22,……, q2, -q2 (q <= m/2),这样就等于是可以双向寻找到可能的空位置。我们称这种方法为二次探测法。
随机探测法
还有一种方法是,在冲突时,对于位移量 di 采用随机函数计算得到,我们称之为随机探测法。
fi(key) = (f(key)+di) MOD m (di是一个随机数列)
再散列函数法
fi(key)=RHi(key) (i=1,2,…,k)
每当发生散列地址冲突时,就换一个散列函数计算,这种方法能够使得关键字不产生聚集,相应的也增加了计算的时间。
链地址法
将所有关键字为同义词的记录存储在一个单链表中,我们称这种表为同义词子表,在散列表中只存储所有同义词子表的头指针。
对于关键字集合{12,67,56,16,25,37, 22,29,15,47,48,34},我们用前面同样的12为除数,进行除留余数法:
公共溢出区法
冲突的关键字放在另外一个单链表中,当无法在散列表中查询时,就在溢出表进行顺序查找。
- 散列表查找(哈希表)知识点
- 查找 之 散列表查找(哈希表)
- 查找--- 哈希表( 散列表)
- 散列表查找(哈希表)
- 散列表(哈希表)查找
- 算法--查找--散列表查找
- 查找——散列表查找(哈希表)
- 散列表(哈希表)查找算法
- 散列表(哈希表)查找算法
- 数据结构_____散列表查找(哈希表)
- 散列表(哈希表)查找算法
- 数据结构之哈希表(散列表查找)
- 散列表查找
- 散列表查找概述
- 散列表的查找
- 散列表查找
- 散列表查找实现
- Java查找算法(五): 散列表查找
- Cocoapods的安装报错
- 安装CocoaPods报错
- iOS开发人员不容错过的10大工具
- iOS开发中调试小技巧
- iOS中的两种主要架构及其优缺点浅析
- 散列表查找(哈希表)知识点
- 浅析我对代码规范的理解
- 熊猫烧香——核心代码
- 初学iPad开发入门
- Mac/Xcode
- iOS 设备的屏幕尺寸一览
- C语言打印当前时间
- iPad开发(Universal Applications)
- Swift