Java二分查找代码实现及原理简要分析

一、代码原理描述

  1. 前提:已经有一个排好序的数组(否则需要先排序)
  2. 定义左边界left, 右边界right, 确定搜索范围,循环执行二分查找(第3、4步骤)
  3. 中间索引的值middle[M] 与带搜索的值T进行比较
  1. midddle[M] == T 表示找到,返回中间索引
  2. midddle[M] > T 表示中间值右侧的其他元素都大于T,无须比较,故设置M-1为右边界,重新查找
  3. midddle[M] < T 表示中间值左侧侧的其他元素都小于T,无须比较,故设置+1为左边界,重新查找
  4. left > right 时,表示没有找到,返回-1

二、代码实现如下

/**
 * 二分查找示例代码
 *
 * @author JIA
 * @date 2022/10/06
 */
public class MyBinarySearch {
    public static void main(String[] args) {
        //测试二分查找方法
        int[] myInt = new int[]{10, 30, 40, 50,60, 90, 100, 120, 200};
        //声明一个变量,保存要查找的值
        int searchValue = 100;
        System.out.println(myBinarySearch(myInt, searchValue));
    }

    /**
     * 二分查找方法代码实现(以整数数组为例)
     *
     * @param ints        源数据所在的整数数组
     * @param searchValue 需要查找的值
     * @return int 返回带查找数据在原数组的下标
     */
    public static int myBinarySearch(int[] ints, int searchValue){
        //声明3个整型变量保存左边界、右边界和 中间的值
        int left = 0, right = ints.length -1;
        int middle = (left + right) / 2;
        //声明一个记录查找次数的变量
        int count = 0;
        while (left <= right) {
            //每次到达这里,表示要进行一次查找操作
            count++;
            if (ints[middle] == searchValue) {
                System.out.println("查找次数:" + count);
                return middle;
            } else if (ints[middle] > searchValue) {
                //中间值大于要查找的值,把右边界修改到中间值的左边一位
                right = middle - 1;
            }else {
                //中间值小于要查找的值,修改左边界为中间值的右边一位
                left = middle + 1;
            }
            //每一轮比较之后,修改中间值:最普通的方式,没有考虑值溢出的问题
            //middle = (left + right) / 2;
            //解决可能导致的值溢出问题:除以2通过无符号右移动位实现或者采用特殊
            //算术运算技巧
            middle =  (left + right)  >>> 1;
            //middle =  left + (right - left) / 2 ;
        }
        //如果查找不到,返回-1
        return -1;
    }
}

三、解决中间下标值溢出的问题

left* 和right都较大的时候,left + right 的运算结果可能超出整数范围

/**
     * 测试数值溢出
     */
    @Test
    public void test() {
        int left = 1;
        //Java中整数的最大值
        int right = Integer.MAX_VALUE;
        //打印结果,输出的结果至少是一个整数
        System.out.println((right + left) / 2);
    }
    //运行结果如下:


解决办法一:使用位运算(无符号右移)避免值溢出

middle = (left + right) >>> 1

解决办法二:使用特殊的运算技巧

middle = lefe + (middle - left) / 2

对于一个有N个数的数组(有序),最多需要java二分查找二维数组 java二分查找代码_二分查找

java二分查找二维数组 java二分查找代码_二分查找_02