查找
线性表的查找
顺序查找
1 | int SerchSqList(SqList &L,int e) |
1 | int SearchSqList2(SqList &L,int e) |
折半查找/二分查找
注意:二分查找仅适用于有序递增或递减
1 | int SearchBin(SqList &L,int e) |
分块查找
见:查找(全)
数表的查找
二叉排序树
1 | BSTree SearchBST(BSTree T, KeyType key) { |
散列表的查找
散列表的基本概念
散列表(哈希表),是一种数据结构,特点是:数据元素的关键字与其存储地址直接相关
如何建立“关键字”与“存储地址”的联系?
通过“散列函数(哈希函数)”:$$Add=H(key)$$实现
- 散列函数和散列地址:$$p=H(key)$$,$$H$$为散列函数,$$p$$为散列地址
- 散列表:一个连续的地址空间,用以存储按散列函数计算得到相应散列地址的数据记录
- 冲突和同义词:$$key_1\not=key_2$$,$$H(key_1)=H(key_2)$$,这种现象称为冲突,$$key_1$$,$$key_2$$互为同义词
散列函数的构造方法
数字分析法
选取数码分布较为均匀的若干位作为散列地址
设关键字是r进制数(如十进制数),而r个数码在各位上出现的频率不一定相同,可能在某些位上分布均匀一些,每种数码出现的机会均等;而在某些位上分布不均匀,只有某几种数码经常出现,此时可选取数码分布较为均匀的若干位作为散列地址。
这种方法适合于已知的关键字集合,若更换了关键字,则需要重新构造新的散列函数。
平方取中法:取关键字的平方值的中间几位作为散列地址
具体取多少位要视实际情况而定。这种方法得到的散列地址与关键字的每位都有关系,因此使得散列地址分布比较均匀,适用于关键字的每位取值都不够均匀或均小于散列地址所需的位数。
折叠法
将关键字分割成位数相同的几部分,然后取这几部分叠加和作为散列地址。根据数叠加的方式,可以把折叠法分为移位叠加、边界叠加。
$$key=45387765213$$,表长为1000:

除留余数法
$$
H(key)=key%p
$$
$$p$$为不大于表长$$m$$但最接近或等于$$m$$的最大质数用质数取模,分布更均匀,冲突更少
直接定址法
$$
H(key)=key 或H(key)=a*key+b
$$
其中,a和b是常数。这种方法计算最简单,且不会产生冲突。它适合关键字的分布基本连续的情况,若关键字分布不连续,空位较多,则会造成存储空间的浪费。
处理冲突的方法
开放地址法
所谓开放定址法,是指可存放新表项的空闲地址既向它的同义词表项开放,又向它的非同义词表项开放。其数学递推公式为:
$$
H_i=(H(key)+d_i)%m,i=1,2…,k(k<=m-1)
$$$$m$$为散列表表长;$$d_i$$为增量序列
根据$$d$$的取值不同,可分为以下三种方法:
线性探测法
$$
d_i=1,2,3,…,m-1
$$
发生冲突时,每次往后探测相邻的下一个单元是否为空线性探测法很容易造成同义词、非同义词的“聚集(堆积)”现象,严重影响查找效率
产生原因:冲突后再探测一定是放在某个连续的位置
二次探测法
$$
d_i=1^2,-1^2,2^2,-2^2,3^2,…,k^2,-k^2(k<=m/2)
$$伪随机探测法
$$
d_i=伪随机数序列
$$
链地址法(拉链法):把具有相同散列地址的记录放在同一个单链表中,称之为同义词单链表

散列表的查找
$$
\alpha=\frac{表中填入的记录值}{散列表的长度}
$$
$$\alpha$$:装填因子$$=ASL_{失败}$$
装填因子表示的是散列表装填的满不满,越大,越空;越小,越满。