【概述】
二分查找(Binary Search),又称折半查找,其仅适用于有序的顺序表或数组,不适用于链表
其算法的基本思想是:将给定关键字 key
与表中中间位置的元素对应的关键字进行比较,中间结点由此将查找表分为两个子表,若相等,则查找成功,若不相等,根据关键字 key
与该中间结点关键字的比较结果来确定下一步查找哪一个子表,这样递归进行,直到查找成功或查找结束发现表中没有这样的结点
【算法分析】
如上图所示,已知 $11$ 个元素的有序表 $\{5,13,19,21,37,56,64,75,80,88,92\}$,要查找值为 $21$ 的元素
用指针 low
指向表的下界,high
指向表的上界,mid
指向表的中间位置,有:
在第一次查找时,将中间位置元素 $56$ 与 key
值 $21$ 比较,由于 $21<56$,说明若待查找元素存在,则必定在范围 $[low,mid-1]$ 内,于是:
指针
high
指向位置 $mid-1$,对应元素 $37$指针
low
指向不变,对应元素 $5$重新计算指针
mid
,有 $mid=(1+5)/2=3$,对应元素 $19$
在第二次查找时,将中间位置元素 $19$ 与 key
值 $21$ 比较,由于 $21>19$,说明若待查找元素存在,则必定在范围 $[mid+1,high]$ 内,于是:
- 指针
low
指向位置 $mid+1$,对应元素 $21$ - 指针
high
指向不变,对应元素 $37$ - 重新计算指针
mid
,有 $mid=(4+5)/2=4$,对应元素 $21$
在第二次查找时,即可得出查找元素 $21$ 在表中存在
【二分查找判定树】
二分查找的查找过程可用下图所示的二叉树来表示,其被称为二分查找判定树
二分查找判定树是一棵平衡二叉树,其中的每一个圆形结点代表一个记录,结点中的值为该记录的关键字值,被称为成功结点;每一个方形结点为树的叶结点,代表查找不成功的情况,被称为失败结点
同时,每个结点值均大于其左孩子结点值,均小于其右孩子结点值
若有序序列有 $n$ 个元素,那么对应的二分查找判定树有 $n$ 个成功结点和 $n+1$ 个失败叶结点
【平均查找长度】
从判定树可以看出,查找成功时的查找长度,为从根结点到目的结点的路径上的结点数,查找不成功时的查找长度,为从根结点到对应失败结点的父结点的路径上的结点数
故而,用二分查找找到给定值的比较次数,最多不会超过树的高度
在查找元素等概率的情况下,二分查找查找成功的平均查找长度为:
其中,$l_i$ 为第 $i$ 层的成功结点数,$h$ 为树的高度,且元素个数为 $n$ 时,树高 $h=\lceil \log_2(n+1) \rceil$
易得二分查找的时间复杂度为:$O(\log_2n)$
在如上图所示的二分查找判定树中,在等概率情况下,有:
【实现】
查找元素
1 | int binarySearch (int key,int a[], int n) { //在有序序列a中查找元素key的位置 |
查找连续函数
除在有序表中查找指定关键字外,二分查找还可以对连续单调函数进行查找
1 |
|