查找
7.2 顺序查找和折半查找
顺序查找
一般线性表
从线性表的一端开始,逐个检查关键字是否满足给定的条件。若查找到某个元素的关键字满足给定条件,则查找成功,返回该元素在线性表中的位置:若己经查找到表的另一端,但还没有查找到符合给定条件的元素,则返回查找失败的信息。
typedef struct{
ELemType *elem;
int TableLen;
}SSTable;
int Search_Seq(SSTable ST, ElemType key){
ST.elem[0]=key; //哨兵
for(i=ST.TableLen;ST.elem[i]!=key;--i)
return i;
}
哨兵可以使得程序不用判断数组是否越界。
一般线性表顺序查找的平均长度为 A S L 成 功 = ∑ i = 1 n P ( n − i + 1 ) ASL_{成功}=\sum_{i=1}^{n}P(n-i+1) ASL成功=∑i=1nP(n−i+1)
当每个元素查找概率相等时 A S L 成 功 = ∑ i = 1 n P ( n − i + 1 ) = n + 1 2 ASL_{成功}=\sum_{i=1}^{n}P(n-i+1)=\frac{n+1}{2} ASL成功=∑i=1nP(n−i+1)=2n+1
当查找不成功时,平均长度为 A S L 不 成 功 = n + 1 ASL_{不成功}=n+1 ASL不成功=n+1
优点
1)对数据存储没有要求;
2)对记录有序性没有要求。
缺点
1)当n较大时,平均查找长度较大,效率低。
有序表
若在查找之前就己经知道表是关键字有序的,则查找失败时可以不用再比较到表的另一端就能返回查找失败的信息,从而降低顺序查找失败的平均查找长度。
假设表 L L L是按关键字从小到大排列的,查找的顺序是从前往后,待查找元素的关键字为 k e y key key,当查找到第 i i i个元素时,发现第 i i i个元素对应的关键字小于 k e y key key但第 i + 1 i+1 i+1个元素对应的关键字大于 k e y key key,这时就可返回查找失败的信息,因为第 i i i个元素之后的元素的关键字均大于 k e y key key,所以表中不存在关键字为 k e y key key的元素。
有序表顺序查找不成功的平均长度为 A S L 不 成 功 = ∑ j = 1 n q j ( l j − 1 ) = 1 + 2 + . . . + n + n n + 1 = n 2 + n n + 1 ASL_{不成功}=\sum_{j=1}^{n}q_j(l_j-1)=\frac{1+2+...+n+n}{n+1}=\frac{n}{2}+\frac{n}{n+1} ASL不成功=∑j=1nqj(lj−1)=n+11+2+...+n+n=2n+n+1n,式中, q j q_j qj是到达第 j j j个失败结点的概率。
※式中 1 + 2 + . . . + n + n n + 1 \frac{1+2+...+n+n}{n+1} n+11+2+...+n+n是因为无论落在最后两个数据的区间内还是大于最后一个数据,查找长度都为 n n n。
折半查找
又称二分查找,仅适用于有序的顺序表。
折半查找的基本思想:首先将给定值 k e y key key与表中中间位置的元素比较,若相等,则查找成功,
返回该元素的存储位置;若不等,则所需查找的元素只能在中间元素以外的前半部分或后半部分
(例如,在查找表升序排列时,若给定值key大于中间元素.则所查找的元素只可能在后半部分)。然后在缩小的范围内继续进行同样的查找,如此重复,直到找到为止,或确定表中没有所需要查找的元素,则查找不成功,返回查找失败的信息。算法如下:
int Binary_Search(SeqList L, ElemType key){
int low=0, high=L.TableLen-1, mid;
while(low<=high){
mid=(high+low)/2;
if(L.elem[mid]==k)
return mid;
else if(L.elem[mid]>key)
high=mid-1;
else
low=mid+1;
}
return -1; //查找失败
}
折半查找可用称为判定树的二叉树描述。
圆形结点:查找表一个记录,结点中的值为该记录的关键字值;
方形叶结点:表示查找不成功的情况。
查找成功时的查找长度为从根结点到目的结点的路径上的结点数;
杳找不成功时的查找长度为从根结点到对应失败结点的父结点的路径上的结点数;
每个结点值均大于其左子结点值,且均小于于其右子结点值。
若有序序列有 n n n个元素,则对应的判定树有 n n n个圆形的非叶结点和 n + 1 n+1 n+1个方形的叶结点。
显然,判定树是一棵平衡二叉树。
查找成功的平均长度:
A S L = 1 n ∑ i = 1 n l i = 1 n ( 1 × 1 + 2 × 2 + . . . + h × 2 h − 1 ) = n + 1 n l o g 2 ( n + 1 ) ≈ l o g 2 ( n + 1 ) − 1 ASL=\frac{1}{n}\sum_{i=1}^nl_i=\frac{1}{n}(1×1+2×2+...+h×2^{h-1})=\frac{n+1}{n}log_2^{(n+1)}≈log_2^(n+1)-1 ASL=n1∑i=1nli=n1(1×1+2×2+...+h×2h−1)=nn+1log2(n+1)≈log2(n+1)−1
其中 h h h是树的高度,并且元素个数为 n n n时树高 h = ⌈ l o g 2 ( n + 1 ) ⌉ h=\lceil log_2^{(n+1)}\rceil h