1. 查找基本概念
- 查找:只有两种情况,查找成功,查找失败
- 查找表:查找的数据集合称为查找表
- 静态查找表 / 动态查找表:区别在于是否只进行查找,还是需要插入,删除处理。
- 平均查找长度:ASL = P1C1 + P2C2 + ... +PnCn
P是查找到第 i 个元素的概率,一般认为 P = 1 / n
C是查找到第 i 个元素的比较次数。
2. 顺序查找
暴力查找,直接从头开始逐个比较,直到找到或者遍历完为止。
值得注意的是哨兵设置,通过哨兵,知道已遍历完。
int Search_Seq(SSTable ST, elemType key)
{
//设置哨兵
ST.elem[0] = key;
// i 指向表的最后,逐个比对,如果没有最后肯定会返回 0
for (i = ST.TableLen; ST.elem[i] != key; --i) ;
return i;
}
以上是查找非顺序表的代码,当查找顺序表的时候也是通过逐个比对,但是若发现此时a[i] > key 则表明表中没有该关键字,可以退出循环。
3. 折半查找(二分查找)
- 基本思路:和序列中间值mid比对,如果key > mid则从右边序列找,如果key < mid 则从右边序列找。在子序列中依旧按照如此法则。
int Binary_Search(SeqList l, elemType key)
{
int low = 0,high = length,mid;
while (low <= high)
{
mid = (low + high) / 2;
if(l.elem[mid] == key)
return mid;
else if(l.elem[mid] > key) //调整high或low的位置,把查找的范围缩小到一半
high = mid - 1;
else
low = mid + 1;
}
return -1;
}
- 由于算法的特性,可以把数据存储在二叉排序树中,称为判定树。
其中,除叶子节点外每个节点存储一个关键字,大于其左孩子,小于其右孩子。其中叶子节点存储的是查找不成功的情况。
ASL = 1/n * (1 * 1 + 2 * 2 + ... + h * 2h - 1) = (n + 1)/n * log2(n + 1) - 1
每一层的查找路径长度为h,每一层有2h - 1个节点
4. 分块查找
基本思路:把记录分为多个块,每个块之中的记录是无序的,但是,块与块之间有序。前面块的最大关键字,要小于后面块的最小关键字。
由此可分析出,查找分为了两个步骤:
- 索引查找:按顺序与块的最大关键字做比较,若小于其最大关键字,则找到块
- 块内查找
ASL = Lb(索引查找) + Ls(块内查找)
网友评论