二分查找(binary search)

二分查找又叫折半查找,要查找的前提是检索结果位于已排序的列表中。

概念

在一个已排序的数组seq中,使用二分查找v,假如这个数组的范围是[low...high],我们要的v就在这个范围里。查找的方法是拿low到high的正中间的值,我们假设是m,来跟v相比,如果m>v,说明我们要查找的v在前数组seq的前半部,否则就在后半部。无论是在前半部还是后半部,将那部分再次折半查找,重复这个过程,知道查找到v值所在的地方。
实现二分查找可以用循环,也可以递归,先给出两种方式的伪代码。

伪代码

使用循环实现

Iterative-Binary-Search(seq, v, low, high)
	while low <= high
		mid = (low + high) / 2
		if v == seq[mid]
			return mid
		elseif v > seq[mid]
			low = mid + 1
		else
			high = mid - 1
	return NIL

使用递归实现

Recursive-Binary-Search(seq, v, low, high)
	if low > high
		return NIL
	mid = (low + high) / 2
	if v == seq[mid]
		return mid
	elseif v > seq[mid]
		return Recursive-Binary-Search(seq,v,mid+1,high)
	else
		return Recursive-Binary-Search(seq,v,low,mid-1)

无论是循环还是递归,当数组为空的时候就结束(low > high),返回空值。当查找到v值的时候,也立即结束。

Python版

使用循环实现

def search(seq, v, low, high):
	while low <= high:
		mid = (low + high) // 2
		if v == seq[mid]:
			return mid
		elif v > seq[mid]:
			low = mid + 1
		else:
			high = mid - 1
	return None

使用递归实现

def search2(seq, v, low , high):
	if low > high:
		return None
	mid = (low + high) // 2
	if v == seq[mid]:
		return mid
	elif v > seq[mid]:
		return search2(seq, v, mid + 1, high)
	else:
		return search2(seq, v, low, mid - 1)

Python版源码: Github-Syler-Fun-Search-Python

Java版

使用循环实现

	public static int search(int[] seq, int v, int low, int high) {
        while (low <= high) {
            int mid = (low + high) / 2;
            if (v == seq[mid]) {
                return mid;
            } else if (v > seq[mid]) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }

        return Integer.MIN_VALUE;
    }

使用递归实现

	public static int search2(int[] seq, int v, int low, int high) {
        if (low > high) {
            return Integer.MIN_VALUE;
        }
        int mid = (low + high) / 2;
        if (v == seq[mid]) {
            return mid;
        } else if (v > seq[mid]) {
            return search2(seq, v, mid + 1, high);
        } else {
            return search2(seq, v, low, mid - 1);
        }
    }

Java版源码: Github-Syler-Fun-Search-Java
但是实际上呢,Java版应该写成这个样子
Arrays.binarySearch(int[] a, int fromIndex, int toIndex, int key)
Java源码中的二分查找是这个样子的:

	public static int binarySearch(int[] a, int fromIndex, int toIndex,
                                   int key) {
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
    }

    // Like public version, but without range checks.
    private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

所以呢,Java里就不用写二分查找算法,用自带的吧。

posted @ 2017-05-06 01:04  hsiaoshun  阅读(15105)  评论(0编辑  收藏  举报