前置知识:查找的基本概念
折半查找
折半查找 又称 二分查找 ,它仅适用于有序的顺序表。
因个人习惯,下文均用二分代替折半。
二分查找的基本思想:
- 首先将给定值 k e y key key与表中中间位置的元素比较,若相等,则查找成功,返回该元素的存储位置;
- 若不等,则所需查找的元素只能在中间元素以外的前半部分或者后半部分,然后在缩小的范围内继续进行同样的查找;
例如,在查找表升序排列时,若 k e y key key大于中间元素,则所查找的元素只可能在后半部分。
重复上述步骤,直到查找成功。或者确定表中没有所需要查找的元素,则查找不成功,返回查找失败的信息。
当二分查找算法选取中间结点时,既可以采用向下取整,又可以采用向上取整。但每次查找的取整方式必须相同。
算法实现如下:
inline int Search_Seq(SSTable L, ElemType key) {
//升序排列
int l = 1, r = L.TableLen, mid;//l为left,r为right
while (l <= r) {
mid = (l + r) / 2;//取中间位置
if (L.elem[mid] == key)return mid;//查找成功则返回所在位置
else if (L.elem[mid] > key)r = mid - 1;//从前半部分继续查找
else l = mid + 1;//从后半部分继续查找
}
return -1;//查找失败,返回-1
}
完整代码可看我的Github:传送门
(补充了降序排列的写法,实际上很简单,把从前半部分继续和后半部分继续对调一下即可)
(图片来自王道考研408数据结构2025)

二分查找的过程可用上图所示的二叉树来描述,称为 判定树 。树中每个圆形结点表示一个记录,结点中的值为该记录的关键字值;树中最下面的叶结点都是方形的,它表示查找失败的区间。
从判定树可以看出,查找成功时的查找长度为从根节点到目的结点的路径上的结点数,而查找失败时的查找长度为从根节点到对应失败结点的父结点的路径上的结点数;每个结点值均大于其左子结点值,且均小于其右子节点值。
二分查找的判定树中,若 m i d = ⌊ ( l + r ) / 2 ⌋ mid=\left \lfloor \left ( l+r \right ) /2 \right \rfloor mid=⌊(l+r)/2⌋,则对于任何一个结点,必有右子树结点数-左子树结点数=0或1;若采用向上取整,则反之。
(下图来自王道考研408数据结构课程视频的截图 - 折半查找)

若有序序列有 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 log 2 ( n + 1 ) − 1 ≈ log 2 ( n + 1 ) − 1 ASL=\frac{1}{n} \sum_{i=1}^{n}l_i=\frac{1}{n} \left ( 1\times 1+ 2\times 2+\cdots + h\times 2^{h-1} \right )=\frac{n+1}{n}\log_{2}{\left ( n+1 \right ) }-1 \approx \log_{2}{\left ( n+1 \right ) }-1 ASL=n1i=1∑nl


235

被折叠的 条评论
为什么被折叠?



