目录
前言
这篇博客主要是介绍顺序折半查找的表示和实现。
1.顺序表的查找
1.定义
静态查找表的顺序存储结构定义如下:
typedef int ElemType;
typedef int Status;
// - - - - - 静态查找表的顺序存储结构 - - - - -
typedef struct {
ElemType * elem; // 数据元素存储空间基址,建表时按实际长度分配0,0号单元留空
int length; // 表长度
} SSTable;
// - - 对数值型关键字
#define EQ(a,b) ((a)==(b))
2.顺序查找的实现过程
顺序查找(Sequential Search)的查找过程为:先设置顺序表的第一个数据元素为哨兵,然后从表中最后一个记录开始,逐个往前查找,找到要查找的数据元素之后则查找成功,返回下标;否则往前遍历查找,一直查找到哨兵元素,则返回下标0。具体比较过程可以看下面的示意图:
图1.顺序查找示意图
核心顺序表查找算法为:
// 顺序表查找
int search_seq(SSTable *ssTable, ElemType key){
ssTable->elem[0] = key;
int i ;
for (i = ssTable->length; !EQ(ssTable->elem[i], key); --i);
return i;
}
3.顺序表查找算法分析
在上述顺序表的查找过程中,我们设置了哨兵,避免了每次都要检测整个表是否查找完毕的过程。第一个哨兵元素起到了监视哨的作用。
假设每次要查找的数据元素在表中的话, 我们看到数据元素的查找次数跟数据的下标有关系,要查找的元素如果位于末尾,只需要查找1次,倒数第二个数据元素需要查找表长-1次,依次类推,当顺序表表长为n的时候,第i个数据元素需要查找n-i+1次,所有元素需要比较的总的次数为1+2+......n = n*(n+1)/2次,假设每个数据元素查找到的概率相同,则每个数据元素被查找到的概率为1/n,那么顺序表的平均查找长度为(n+1)/2。
假如每次都能查找成功和失败的概率都相同,算法如下,这里偷个懒,直接贴个图。
我们可以看出当表的长度n比较大的时候,查找的次数也会增大。
2.有序表的查找
1.折半查找的过程
当用有序表表示静态查找表的时候,可以使用折半查找来实现。
具体过程如下:先确定待查记录所在的范围,然后逐步缩小范围知道找到或者找不到改记录为止。
我这里也写了一个程序表示折半查找的过程:
图2.折半查找过程
核心查找算法如下:
// 折半查找
Status binarySearch(SSTable *ssTable, ElemType key, int *locate) {
int low = 1, high = ssTable->length;
while (low <= high) {
int mid = (low + high) / 2;
if (ssTable->elem[mid] == key) {
*locate = mid;
return 1; // 找到了
} else if (ssTable->elem[mid] < key) {
low = mid + 1; // 在右半部分继续查找
} else {
high = mid - 1; // 在左半部分继续查找
}
}
return 0; // 没找到
}
2.折半查找的算法分析
我们可以使用二叉树来表示折半查找的过程,折半查找成功的时候进行比较的关键字个数最多不超过树的深度,结论参考严蔚敏老师的数据结构,下面直接贴出来结论:
图3.折半查找的平均查找长度
3.静态树表的查找
这里太复杂了,有时间研究明白了在补充上吧。
4.索引顺序表的查找
这里太复杂了,有时间研究明白了在补充上吧。