今天刚好学习了二分查找算法,记录一下防止忘记。
搜索算法就是在一个项目集合中找出一个或一组具有某种特点的项目。我们将项目集合称为 搜索空间。它可以很具体,比如一组电子病历;也可以很抽象,比如所有整数的集合。在实际工 作中,大量问题都可以转换为搜索问题。
如果我们对列表中元素的排序顺序一无所知,时间复杂度为O(len(L))是我们能做到的最好的情况。
因此二分查找必须保证元素有序排列,否则很有可能出现错误。
二分查找的原理就在于将需要查找的值x与搜索空间元素的中间值(middle)进行比较,假设搜索空间元素为升序排列,如果x=middle,这将是最好的结果,直接返回middle作为查找值,这时时间复杂度为O(1),如果x>middle,那接下来只需要在(middle,end]中继续查找,因为元素是有序排列的,因此x绝不会落在[start,middle)区间内。
以此类推,
在(middle,start]区间中,再继续选择一个中间值与x作比较,如果x >new_middle,重复上述操作,继续分割搜索空间,直到找到x的对应值。原理如图所示。
python实现如下:
def search1(L,e):
"""假设L是列表,其中元素按升序排列。
ascending order. 如果e是L中的元素,
则返回True,否则返回False"""
def binarySearch(L,e,low,high):
# 递归终止的条件
if low == high:
return L[low] == e
mid = (low + high) // 2
if L[mid] == e:
return True
elif L[mid] > e:
if low == mid:
return False
else:
return binarySearch(L,e,low,mid-1)
else:
return binarySearch(L,e,mid+1,high)
if len(L) == 0:
return False
else:
return binarySearch(L,e,0,len(L)-1)
Java实现如下:
import java.util.Arrays;
public class BinarySearch
{
public static int rank(int key , int[] a)
{
//数组必须是有序的
int lo = 0 ;
int hi = a.length - 1 ;
while (lo <= hi)
{
// 被查找的键要么不存在,要么必然存在于a[lo..hi]之中
int mid = lo + (hi - lo) / 2
if (key < a[mid]) hi = mid - 1 ;
else if (key > a[mid]) lo = mid + 1 ;
else return mid ;
}
return -1 ;
}