二分法查找的bug与解决

代码需求如下:

/* 
* 二分法查找操作:使用二分法查找有序数组中元素。找到返回索引,不存在 输出-1。
* 分析:二分法查找的前提是数组有序。
* 假如有一组数为3,12,24,36,55,68,75,88要查给定的值24.可设三个变量front
* ,mid,end分别指向数据的上界,中间和下界,mid=(front+end)/2.  
*/

原始代码如下:

public class Test29{
	public static void main(String[] args){
		int[] arr = {3,12,24,36,55,68,75,88};
		Arrays.sort(arr);
		//数组上界、下界、中间值
		int front = 0;
		int end = arr.length-1;
		int mid = 0;
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入要查找的整数:");//输入5出现Bug,why?  front=0,end=1 进入死循环
		int num = sc.nextInt();
		//记录查询次数
		int count = 0;
		//输入数据是否存在于数组中,true表示存在,false表示不存在
		boolean flag = false;
		while(front <= end){
			count++;
			/* if(front > end){//front不可能大于end
				break;
			} */
			mid = (front + end) / 2;
			if(num > arr[mid]){
				front = mid;
			}else if(num == arr[mid]){
				flag = true;
				break;
			}else{
				end = mid;
			}
		}
		if(flag){
			System.out.println("该数据位于数组索引" + mid + "处," + "查找次数:" + count);
		}else{
			System.out.println("-1," + "查找次数:" + count);
		}
	}
}
这段代码写完之后,粗看没发现什么bug,但是测试的时候出现了问题,输入数字5之后进入了死循环。此时front=0,end=1。此时开始反推逻辑,其实在if的第二个分支,已经将输入的数值与中间值进行了比较,所以需要将插入的索引位置前移或后移。如果不进行这种操作,那么就很可能进入一直与中间值比较的情况,从而进入死循环。

于是翻看了Arrays类下面的二分法查找源码:

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.
    }
很明显,源码在进行中值操作的时候,进行了前移( high = mid - 1)或后移(  low = mid + 1),这样就避免了进入无限与中值比较的情况。

修改代码如下,问题解决:

import java.util.Arrays;
import java.util.Scanner;

public class Test29{
	public static void main(String[] args){
		int[] arr = {3,12,24,36,55,68,75,88};
		Arrays.sort(arr);
		//数组上界、下界、中间值
		int front = 0;
		int end = arr.length-1;
		int mid = 0;
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入要查找的整数:");//输入5出现Bug,why?  front=0,end=1 进入死循环
		int num = sc.nextInt();
		//记录查询次数
		int count = 0;
		//输入数据是否存在于数组中,true表示存在,false表示不存在
		boolean flag = false;
		while(front <= end){
			count++;
			/* if(front > end){//front不可能大于end
				break;
			} */
			mid = (front + end) / 2;
			if(num > arr[mid]){
				front = mid + 1;
			}else if(num == arr[mid]){
				flag = true;
				break;
			}else{
				end = mid - 1;
			}
		}
		if(flag){
			System.out.println("该数据位于数组索引" + mid + "处," + "查找次数:" + count);
		}else{
			System.out.println("-1," + "查找次数:" + count);
		}
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值