----------------------android培训、java培训、期待与您交流! ----------------------
折半查找( Binary Search)是查找有序序列的标准过程,比顺序查找有效得多,但它需要元素是有序的。它把查找序列平均分成两半,如划分点元素不是我们所要查找的元素,则在有可能包含查找元素的子序列中查找,重复上述查找过程,直到找到或找遍为止。
当你查字典时,或许你使用的就是折半查找。
算法1 折半查找
前提条件(输入):s={ } 是n个类型为x的有序值序列。
后置条件(输出)当某个 时,返回索引值i,否则,返回-1。
1.令ss为序列s的子序列,并置初值为s。
2.当子序列ss为空时,返回-1。
3.(不变式)当原序列s中包含x时,x必然在子序列ss中。
4. 令为子序列ss的中间元素。
5.若则返回索引i。
6. 假如,重复步骤2~7,在子序列{ }中继续查找与相等的元素。
7. 重复步骤2~7,在子序列{ }中查找与x相等的元素。
注意,在算法1的前提条件中,序列必须是事先排序的。
在java.util.Arrays中实现了折半查找算法。
例1 折半查找算法
public static int binarySearch(int [] a,int x)
{
//前置条件:a[0]<=a[1]<=...<=a[a.length-1];
//后置条件:returns i;if i >=0,then a[i]==x;
// otherwise i == -1;
int lo=0,hi=a.length-1;
while (lo <= hi) //步骤1
{//不变式:if a[j] == x then lo<=j<=hi; //步骤3
int i = (hi+lo)/2; //步骤4
if(a[i]==x) return i; //步骤5
else if(a[i]<x) lo = i+1; //步骤6
else hi = i-1; //步骤7
}
return -1 ; //步骤2
}
定理1 折半查找算法是正确的。
证明:循环迭代开始时,子序列为输入原序列,循环不变式为真。在随后的各循环迭代布中;下一迭代步中的子序列是当前子序列中去掉不包含元素那半段后所剩余的部分,因此,如果x在原序列中,则x必在下一迭代步中将要查找的子序列在中,因此,在每一个循环步中,不变式总为真。
在每次迭代中,当 时,将返回索引值i。否则,子序列长度将减少百分之五十多。
因原序列为有限个元素,循环比在有限步内终止,因此,当算法终止于循环中部(步骤5)时,将返回索引值i。或当终止于循环末尾(步骤6或7)时,将返回-1。从循环中部返回索引值i时,表明 ,否则,循环终止于hi<lo,也即当前子序列为空序列。在这种情况下,从循环不变式可知, 不在原序列中。
定理2 折半查找算法的运行时间为O(lg n)
证明:从定理2.3的证明过程可知,循环迭代次数最多为n能被2除(取整)的次数加1,也即n以2为底的对数取整加1,因此,算法的时间复杂度为O(lg n)。
例2 测试折半查找算法
import schaums.dswj.ArraysDemo;
public class Ex0208
{
private static final int SIZE = 16;
private static final int START= 40;
private static final int RANGE = 20;
private static int [] a = new int[SIZE];
public static void main(String [] args)
{
ArraysDemo.load(a,START,RANGE);
ArraysDemo.print(a);
test();
java.util.Arrays.sort(a);
ArraysDemo.print(a);
test();
test();
test();
}
public static void test()
{
int x = ArraysDemo.load(START,RANGE);
System.out.print("Searching for x =" +x+":\t");
int i = ArraysDemo.binarySearch(a,x);
if(i>=0) System.out.println("a["+i+"]="+a[i]);
else System.out.println("i = "+i+" --> x not found");
}
}
该程序的输出为:
本测试程序中,test() 被调用4次,从程序中可以看出,test()调用折半查找算法在由load()产生的数组中查找x,第一次查找x=48,尽管数组a[8]=48,但由于数组没有事先排序,因此折半查找失败,没有找到。在第二次调用test()之前,使用java.util.Arrays.sort(a)对数组a进行排序,这样,在a[11]找到x=55。请注意的是,此处并不是x=55的第一次出现,因为它还出现在a[10]处。由于折半查找算法不是顺序的,当某值不只一次出现时,算法返回的索引值是不易预见的。第三次查找时,x=41,在a[4]处找到。第四次调用test()查找x=58,没有找到,返回值为-1。
---------------------- android培训、java培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net/heima