`

java算法基础--二分查找

阅读更多
基本概念:二分查找又称折半查找,要求待查找数组有序;优点是比较次数少,查找速度快;其缺点是要求待查表为有序表。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

基本思想:首先假设已排序好的序列是升序,将要查找的元素与序列中间的元素比较,若相等,则查找成功;若待查找元素比中间元素大,则查找除去中间元素的后半部分序列,反之,则查找去除中间元素的前半部分序列,直到查到相同的元素或者所查找的序列范围为空为止。

实现思路:还是假设数组元素是升序的,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的value作比较,如果value=a[n/2]则找到value,算法终止。如 果value<a[n/2],则我们只要在数组a的左半部继续查找value。如果value>a[n/2],则我们只要在数组a的右半部继续查找value。

性能分析:若数组长度为n,则算法复杂度为O(log n)

具体代码:(非递归版)
public class binarySearchTest {

	public static int binarySearch(int[] a,int value)
	{
		//若数组为空,则返回-1
		if(a.length == 0 )
		{
			return -1;
		}
		
		int low = 0;
		int high = a.length - 1;
		
		while(low <= high)
		{
			int mid = (low + high) / 2;//这个是有BUG的
			
			//打印中间元素选取过程,只是显示过程,与算法本身无关
			for(int i = 0;i < a.length;i++)
			{
				System.out.print(a[i]);
				if(i == mid)
				{
					System.out.print("#");//用#号表示中间元素
				}
				System.out.print(" ");//各个元素用空格隔开
			}
			System.out.println();//每次选取过程换行
			
			//核心
			if(value == a[mid])
			{
				return mid;
			}
			else if(value > a[mid])
			{
				low = mid + 1;
			}
			else
			{
				high = mid - 1;
			}
		}
		
		return -1; //不存在该元素则返回-1   
	}
	public static void main(String[] args) {
		int[] a={1,3,4,5,8,7,9,11,15};  
		System.out.println(binarySearch(a,9));
		
	}
}


具体代码:(递归版)
public class binarySearchRecursionTest {
	
	public static int binarySearchRecursion(int[] a,int fromIndex,int toIndex,int key)
	{
		if(fromIndex > toIndex) return -1;
		int midIndex = (fromIndex + toIndex) / 2;//这个是有BUG的
		int midVal = a[midIndex];
		
		if(midVal > key)
		{
			return binarySearchRecursion(a,fromIndex,midIndex - 1,key);
		}
		else if(midVal <key)
		{
			return binarySearchRecursion(a, midIndex + 1, toIndex, key);
		}
		else
		{
			return midIndex;
		}
		
	}

	public static void main(String[] args) {
		int[] a={1,3,4,5,8,7,9,11,15};  
		System.out.println(binarySearchRecursion(a,0,a.length,9));
	}
}


代码分析早前的jdk中Arrays类中的二分查找存在一个临界值的bug,bug在代码中的int mid = (low + high) / 2;当low + high大于正int范围时就会溢出,会抛出ArrayIndexOutOfBoundsException 异常。

解决办法:将int mid = (low + high) / 2修改为
                 int mid = low + ((high - low) / 2);
或者         int mid = (low + high) >>> 1;(最新的java.util.Arrays中用的是这个办法)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics