一、静态查找表
查找表(table):同类型的DE(或记录)构成的集合
查找表上的基本运算:
建立查找表create(ST,n)
查找search(ST,k)
遍历查找表traverse(ST)
查找:在查找表中确定与给定值相等的DE的过程。
查找结果:
查找成功(table中存在给定的记录)
查找不成功(table中不存在给定值的记录)
查找表分为:
静态查找表(对查找表中的数据元素不进行插入或删除操作)
动态查找表(对查找表中的数据元素可进行插入和删除操作)
1、顺序表的查找
FUNC seqsrch1(r:sqlisttp;k:keytype):integer;
r[0].key:=k;i:=n;
WHILE r[i].key <>k DO i:=i-1;
RETURN(i)
ENDF;{seqsrch1}
1)查找过程:
从n开始,依次与k进行比较,若相等则查找成功;否则,继续进行,直到与r[0].key比较为止。
2)算法分析:
(1)算法结构应由一个循环构成;
(2)循环结束有两种可能:
3)查找成功:r[i].key=k
查找不成功 i=0
4)查找方向可换
FUNC seqsrch2(r:sqlisttp;k:keytype):integer;
r[n+1].key:=k;i:=1;
WHILE r[i].key <>k DO i:=i+1;
IFi=n+1 THEN RETURN(0)
ELSE RETURN(i)
ENDF;{seqsrch2}
平均查找长度(ASL)
查找过程中,给定值需与关键字比较的次数的期望值。
ASL=PiCi
其中:Pi为查找第i个记录的概率;
Ci为找到第i个记录时,已比较的次数。
顺序查找的平均查找长度ASLss=np1+(n-1)p2+……+pn
当pi=1/n时,ASLss=PiCi=(n+1)/2
2、有序表的查找
有序表:查找表中记录按关键字有序排列的表。即:r[i].key<= r[i+1].key i=1,2,…,n-1
折半查找:
要求:查找表为有序表;
查找过程:先确定待查记录范围;然后逐步缩小范围;直到查找成功或不成功。
折半查找算法
FUNC binsrch(r:ordlisttp;k:keytype):integer;
low:=1;high:=n;found:=false;
WHILE low≤high AND NOTfound DO
[mid:=(low+high)DIV 2
CASE
k>r[mid].key:low:=mid+1;
k=r[mid].key:found:=true;
k<r[mid].key:high:=mid-1;
ENDC;
]
IFfound THEN RETURN(mid)ELSE RETURN(i)
ENDF;{ binsrch }
3.索引顺序表的查找(分块查找)
索引表:
1)按表中记录的关键字分块,R1,R2,……,RL
要求:第Rk块中的所有关键字<Rk+1块中的所有关键字 k=1,2,……,L-1,称为“分块有序”
2)对每块建立一个索引项,包含以两项内容:
(1)关键字项:为该块中最大关键字值;
(2)指针项:为该块第一个记录在表中位置。
3)所有索引项组成索引表
查找分为两步:
1)确定待查记录所在块;(可以用顺序或折半查找)
2)在块内顺序查找。(只能用顺序查找)
分块查找表的平均查找长度ASL=Lb+Lw
其中:Lb为查索引表确定所在块的平均查找长度;
Lw为在块内查找记录的平均查找长度;
二、动态查找表
动态查找表的特点:
表结构本身是在查找过程中动态生成的。即查找不成功时,将该记录插入动态查找表中
1、二叉排序树(Binary Sort Tree)(二叉查找树)
1)BST定义:
BST或者是一棵空树,或者是具有如下性质的BT:
若左子树非空,则左子树上所有结点的值均小于根结点的值;
若右子树非空,则右子树上所有结点的值均大于根结点的值;
左、右子树也为BST
2)查找过程为:
(1)当前BST非空时,将给定值k与当前根结点的关键字比较;
(2)若相等,查找成功,结束;
若k小于当前根结点的关键字,则将左子树作为当前BST;
若k大于当前根结点的关键字,则将右子树作为当前BST;
(3)重复(1)。
3)BST的特点:
(1)中序遍历BST可得到一个关键字的有序序列。
(2)在BST上插入新结点时,不必移动其他结点,仅需改动某结点的指针(因新结点总是BST上的一个新叶结点T。
(3)BST既具有类似折半查找的特性(与BST的平衡度有关)又采用了链表存储结构(折半查找不能为链表存储结构),因此,对于经常要进行查找、插入和删除记录的有序表,采用BST尤其适合。
4.BST的查找分析
BST上查找过程与折半查找类似,是从根结点到所找到结点的一条路径,与给定值比较次数等于该路径长度+1(即结点所在层次数),最大次数不超过树的深度。
但长度为n的所有折半查找表对应的判定树是唯一的,而含有n个结点的BST却不唯一。
因此,含有n个结点的BST的ASL和树的形态有关。
最差情况是BST退化为单支树,其深度为n,ASL=(n+1)/2(同顺序查找)
最好情况与折半查找相同,ASL=log2n
随机情况下,平均查找长度为1+4logn
为了避免出现单支树,在构成BST的过程中可进行“平衡化”处理。
2、平衡二叉树(Balanced Binary Tree)(又称AVL树)
1)AVL树定义:
AVL树或者是一棵空树,或者是具有下列性质的BT:
左、右子树均为AVL
且任一左、右子树的深度只差的绝对值不超过1
称某结点左子树的深度-右子树的深度为该结点的平衡因子
2)AVL树的结点
AVL树上任何结点的平衡因子只可能为-1,0或1;
AVL树的深度与logn同数量级;
完全二叉树一定是AVL,AVL树不一定是完全二叉树
3)BST变为AVL树
三、哈希查找表
通过计算来查找的新型方法——哈希法(Hash)或称杂凑法、散列法。
设关键字集合为A,地址空间为D,哈希法就是在A和D之间建立一种函数关系H,通过计算函数H(k),就能得到关键字k的地址
设D是长度为n的表,A是含m个记录的关键字集合,如果存在一个函数H,使得对A中任一关键字k,均有0≤H(Ki)≤n-1 i=1,2,……,m
同时,Ki所标示的记录Ri在表D中的地址是H(Ki),
则称函数H为关键字集合A到地址D之间的哈希函数,地址空间D为哈希表。
哈希函数不一定是一对一的,产生地址冲突
在应用哈希查找方法时,主要解决两个技术问题:
一是构造好哈希函数的方法;二是研究冲突解决的方法
1、哈希函数构造方法
计算简单容易,冲突极少
1)直接哈希函数
取关键字本身或关键字的某个线性函数值作为哈希地址
即:H(key)=key 或H(key)=a*key+b
2)数字分析法
设n个d位数的关键字,由r个不同的符号组成,此r个符号在关键字的各位出现的频率不一定相同,可能在某些位上均匀分布,即每个符号出现的次数都接近于n/r次,而在另外一些位上分布不均匀。则选择其中分布均匀的s位作为哈希地址,即H(key)=“key中数字均匀分布的s位”。H(key)
3)平均取中法
取关键字平方后的中间几位作为哈希地址,即哈希函数为:H(key)=“key平方的中间几位”其中,所取的位数由哈希表的大小确定。
4)折叠法
将关键字分割成位数相等的几部分(最后一部分位数可以不同),取这几部分叠加和(舍去高位的进位)作为哈希地址。位数由存储地址的位数确定
相加时有两种方法:
移位折叠加法:即将每部分得最后一位对齐,然后相加;
间界折叠加法:即将关键字看做一纸条,从一端向另一端沿间界逐次折叠,然后对齐相加
5)除留余数法
取关键字被某个不大于哈希表长m的数p除后的余数为哈希地址。
即H(key)=key MOD p,p≤m
P的选择很重要,选得不好回产生很多冲突,通常选择p≤m的某个质数。
6)随机数法
选择一个随机含糊,取关键字的随机函数值作为它的哈希地址。
即H(key)=random(key)
2、处理冲突的方法
冲突是指由关键字得到的Hash地址上已有其他地址,处理冲突就是为该关键字找到另一个“空”的Hash地址。
1)开放定址法
Hi=(H(key)+di)mod m i=1,2,……,m-1;
其中:
Hi为第i次冲突的地址;
H(key)为Hash函数;
m为Hash表表长;
di为增量序列
线性探测再散列:di=1,2,3,……,m-1
二次线性探测再散列:di=12,-12,22,-22,32,……,±k2 |±k|≤m-1
伪随机探测再散列:di=伪随机序列
2)再哈希法
Hi=RHi(key) i=1,2,……,n
RHi为不同哈希函数
用n个不同哈希函数排成一个序列,当发生冲突时,由RHi确定第i次冲突的地址Hi
3)链地址法
将关键字发生冲突的记录存储在一个线性链表中
4)公共溢出区法
将同哈希表中关键字发生冲突的所有记录填入一个溢出表中。