数据结构与算法【二分查找】Java实现

需求:在有序数组 A 内,查找值target

  • 如果找到返回索引
  • 如果找不到返回 -1

前提

给定一个内含 n 个元素的有序数组 A,一个待查值 target

1

设置 i=0,j=n-1

2

如果 i \gt j,结束查找,没找到

3

设置 m = (i+j)/2 ,m 为中间索引并向下取整

4

如果 target < A[m] 设置 j = m - 1,跳到第2步

5

如果 A[m] < target 设置 i = m + 1,跳到第2步

6

如果 A[m] = target,结束查找,找到了

代码实现基础版

public class search_binary {
    public static void main(String[] args) {
        int[] a = {9, 18,21, 28, 32,40,46};
        int index = search(a, 32);
        System.out.println("查找结果为:" + index);
    }

    public static int search(int[] a, int target) {
        int i = 0;
        int j = a.length - 1;
        while (i <= j) {
            int m = (i + j) / 2;
            if (a[m] < target) {
                //说明要查找的数在右边
                i = m + 1;
            } else if (a[m] > target) {
                j = m - 1;
            } else {
                return m;
            }
        }
        return -1;
    }
}

由于Java中int类型会自动向下取整,因此我们不需要考虑m带小数的情况。

查找过程如下

数据结构与算法【二分查找】Java实现_第1张图片

数据结构与算法【二分查找】Java实现_第2张图片

数据结构与算法【二分查找】Java实现_第3张图片

数据结构与算法【二分查找】Java实现_第4张图片

数据结构与算法【二分查找】Java实现_第5张图片

数据结构与算法【二分查找】Java实现_第6张图片

但是它仍存在一些问题。那就是Integer数值取值问题,m有可能会变为负数,情景再现。

    public static void main(String[] args) {
        int i = 0;
        int j = Integer.MAX_VALUE;//j表示int类型所能表达的最大数
        int m = (i + j) / 2;
        System.out.println(m);
        //假设目标值在m右侧
        i = m + 1;
        m = (i + j) / 2;
        System.out.println(m);
    }

1073741823

-536870912

之所以会出现这种问题,是因为m的值超出了int所能表达的最大值。在计算机中,一个数字最后都会由二进制表示,而int类型能表达的范围是-2147483648~2147483647,最大值转化为二级制为

数据结构与算法【二分查找】Java实现_第7张图片

可以看到第一位数字为0,这是因为Java中,是需要把二进制数字中的第一位数字当作符号位的(0为正,1为负)。超过最大值的二进制表示,第一位就会变为1,在Java中自然会被识别成一个负数。为了避免这个问题,我们可以采用右移运算,也就是将所有的二进制右移一位(相当于除以2)。具体代码实现如下

public static int binarySearch(int[] a, int target) {
    int i = 0, j = a.length - 1;
    while (i <= j) {
        int m = (i + j) >>> 1;
        if (target < a[m]) {          // 在左边
            j = m - 1;
        } else if (a[m] < target) {   // 在右边
            i = m + 1;
        } else {
            return m;
        }
    }
    return -1;
}

代码实现改动版 

    public static int binarySearch(int[] a, int target) {
        int i = 0, j = a.length;
        while (i < j) {
            int m = (i + j) >>> 1;
            if (target < a[m]) {			// 在左边
                j = m;
            } else if (a[m] < target) {		// 在右边
                i = m + 1;
            } else {
                return m;
            }
        }
        return -1;
    }

与基础版相比,改动版就是修改了 j 的边界值,将j的下次一次取值变为m。首先我们需要清楚的是,a[m]不是目标值是,下标为m的数字是已经判断过了的,因此可以充当 j 的边界值。

流程如下,我们查找29的下标

数据结构与算法【二分查找】Java实现_第8张图片

数据结构与算法【二分查找】Java实现_第9张图片

数据结构与算法【二分查找】Java实现_第10张图片

数据结构与算法【二分查找】Java实现_第11张图片

数据结构与算法【二分查找】Java实现_第12张图片

数据结构与算法【二分查找】Java实现_第13张图片

你可能感兴趣的:(java,数据结构)