折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。
【基本思想】
将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。如果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。如果x>a[n/2],则我们只要在数组a的右半部继续搜索x。
二分搜索法的应用极其广泛,而且它的思想易于理解。第一个二分搜索算法早在1946 年就出现了,但是第一个完全正确的二分搜索算法直到1962年才出现。Bentley在他的著作《Writing Correct Programs》中写道,90%的计算机专家不能在2小时内写出完全正确的二分搜索算法。问题的关键在于准确地制定各次查找范围的边界以及终止条件的确定,正确地归纳奇偶数的各种情况,其实整理后可以发现它的具体算法是很直观的。
C# 描述
一: 经典二分查找算法
public static int BinarySearch(int[] array, int key) { int low = 0; int high = array.Length - 1; int middle = 0; while (low <= high) { middle = (low + high) / 2; int middleValue = array[middle]; if (middleValue < key) { low = middle + 1; } else if (middleValue > key) { high = middle - 1; } else { return middle; } } return -(low + 1); }
二:递归实现(Recuition)
public static int BinarySearchRecuition(int[] array, int key, int low, int high) { int middle = (low + high) / 2; if (low < high) { if (key <= array[middle]) { BinarySearchRecuition(array, key, low, middle); } else { BinarySearchRecuition(array, key, middle + 1, high); } } else if (low == high) { if (key == array[middle]) { return low; } else { return -1; } } else { return -1; } return -1; }
三:迭代实现(Iteration)
public static int BinarySearchIteration(int[] array, int key) { int low = 0; int high = array.Length - 1; int middle = 0; while (low < high) { middle = (low + high) / 2; if (key > array[middle]) { low = middle + 1; } else { high = middle; } } if (low > high) { return -1; } else { if (key == array[low]) { return low; } else { return -1; } } }
以上就是三种实现二分查找算法的程序源代码
详情可参考:http://blog.minidx.com/2008/02/03/468.html
以下是二分查找出关键字key 的位置的函数
C#
public static int BinarySearch(int[] array, int key, int low, int high) { //At the last position if(key >= array[high]) { return high + 1; } int middle = 0; while (low <= high) { middle = (low + high) / 2; int middleValue = array[middle]; if (middleValue < key) { low = middle + 1; } else if (middleValue > key) { high = middle - 1; } else { return middle; } } return middle; }
当确定key在一个有序数组中的位置的时候
例如
有序数组 int[] array = new int[6] { 13, 27, 38, 65, 76, 97 };
若key = 1,13, 得到结果是0
若key= 15,27,得到的结果是1
若key = 77,80,得到的结果是5
若key = 97,100,得到的结果是6
这个函数在二分查找插入排序的时候很有用(自认为),当然此方法也可以写成递归或者迭代的方式,原理根二分查找一样的.
在以上的代码中有一个"经典"的Bug:就是 代码:
middle = (low + high) / 2
当high的值接近2 ^ 31 - 1 的时候
那么middle 就有可能溢出
所以可以改成如下:
middle = low + ((high - low) / 2);或
middle = (low + high) >>> 1;