查找分为两种:
静态查找: 只查找,不改变数据元素集内的数据元素;
动态查找:既查找,又改变(增减)集合内的数据元素。
静态查找又分为三种:顺序查找,折半查找,索引顺序查找(分块查找)
关键字:在实际应用问题中,每个记录一般包含有多个数据域,查找是根据其中某一个指定的域进行的,这个作为查找依据的域称关键字(key)。
主关键字: 可唯一标识一个记录的关键字。例:学号
次关键字:可识别若干记录的关键字。例:性别
一.顺序查找:
1.思想:从表的一端开始,逐个进行记录的关键 字和给定值的比较。
2.算法实现:
int SearchSeq(SSTable ST[],int n,int key)改进算法:
{
int i=n;
while(ST[i].key!=key)&&(i>=0) i--;
return i;
}
int SearchSeq(SSTable ST[],int n,int key)
{
ST[0].key=key;//避免每次比较的时候都要判断是否查找结束,设置一个监视哨
int i=n;
while(ST[i].key!=key)i--;
return i;
}
3.ASL(平均查找长度:表示找到相应的关键字预计比较的次数)
ASL=,其中Ci为关键字与表中找到的每i个元素比较的次数,Pi为第i个元素在表中出现的概率(一般认为相等),所以
(1) 查找成功时的ASL==1/n*(n+1)*n/2=(n+1)/2.
(2)查找不成功的比较次数ASL=n+1次
所以顺序查找的平均查找长度为(1)+(2)/2=3(n+1)/4
4.算法优缺点分析:
优点:算法简单,无需排序,采用顺序和链式存储均可。
缺点:当n很大时,平均查找长度较大。
二.折半查找:
1.算法思想:把静态查找表分为一个区间,每次都用关键字key和区间中间的一个元素(low+high)/2=mid相比,
如果相等,则返回结果; 如果key>SSTable[mid],low=mid+1,在右半部分找; 如果key<SSTable[mid],high=low-1,在左半部分找。
2.代码实现:
int Search_Bin( SSTable ST[ ], int n, int key)
{
int low, high,mid;
low=1; high=n;
while(low<=high) {
mid=(low+high)/2;
if (ST[mid].key == key) return mid;
else if ( key< ST[mid].key) high=mid-1;
else low=mid+1;
}
return 0;
}
3.ASL分析:
(1)二分查找判定树:把当前查找区间的中点作为根结点,左子区间和右子区间分别作为根的左子树和右子树,左子区间和右子区间再按类似的方法。
查找成功:
*比较次数=二叉树结点数=二叉树深度
比较次数<=树的深度(└ log2n ┘ + 1(向下取整))
查找不成功:
比较次数<=树的深度(└ log2n ┘ + 1(向下取整))
(2) 若在树的高度为k的满二叉树n=2k-1中,树的第i层有2i-1个结点,树的第i层结点的全部查询次数为i*2i-1,在等概率的情况下,Pi=1/n,因此,折半查找的平均查 找长度为
4.优缺点分析:
优点:对于有序表查找速度很快;
缺点:只适用于有序,顺序存储,并且元素改动的少的查找表。
我们可以通过举例证明当上述有序表的各个元素查找的概率不同的时候,折半查找的ASL并不是最优的,从而引出第三种查找算法。
三.静态树表的查找:
1.静态最优查找树(类似于哈夫曼树)
若只考虑查找成功的情况,则使查找性能达最佳的判定树是其带权内路径长度之和PH值取最小值的二叉树。
其中:n为二叉树上结点的个数(即有序表的长度);hi为第i个结点在二叉树上的层次数;结点的权wi=cpi(i=1,2,…,n),其中pi为结点的查找概率,c为某个常 量。称PH值取最小的二叉树为静态最优查找树(Static Optimal Search Tree)
由于构造静态最优查找树花费的时间代价较高,因此需要构造近似最优查找树的有效算法
2.次优查找树(近似最优查找树)
构造次优查找树方法:
当数据很多时,顺序查找费时;折半查找需要对元素先排序,也很费时,这时就需要一种折中的算法了。
四.索引顺序表的查找(分块查找):
1.算法思想:
把全部元素分成若干块,块内之间的元素不需要排序,然后另外开辟一个索引表来存放每个块内的最大关键字和每个块内的元素开始标号,当要查找某个元素时,
先查找块号(折半或顺序查找),再根据开始标号在那个块中顺序查找。
2.ASL分析:
平均查找长度: ASLbs= Lb + Lw (Lb表示块查找长度,Lw表示块内查找长度)
若将长度为 n 的表均分成 b 块,每块含 s 个记录 (b = n/s(向下取整)); 并设表中每个记录的查找概率相等,则每块查找的概率为 1/b, 块中每个记录的 查找概率为 1/s。
(1)顺序查找块号,顺序查找块内元素:
(2).折半查找块号,顺序查找块内元素:
总结: