19、二分查找

一、简单介绍

二分查找针对的是一个有序的数据集合,查找思想有点类似分治思想。每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。O(logn) 惊人的查找速度。

我们二分查找可以分成两个情况,一种是不存在重复元素。另外一种是出现重复元素的情况。

二、代码实现

1、不存在重复元素的二分查找

  /**
     * 二分查找
     *
     * @param data
     * @param value
     */
    public static int BinarySearch(int[] data, int value) {
        return binarySearch(data, 0, data.length - 1, value);
    }

    /**
     * 通过二分查找进行查找元素
     *
     * @param data
     * @param l
     * @param r
     * @param value
     * @return 返回下标,如果没有找到就返回-1
     */
    private static int binarySearch(int[] data, int l, int r, int value) {
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if (value == data[mid]) {
                return mid;
            } else if (value > data[mid]) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return -1;
    }

2、不存在重复元素的二分查询的递归实现

  /**
     * 递归实现
     *
     * @param data
     * @param l
     * @param r
     * @param value
     * @return
     */
    private static int binarySearch2(int[] data, int l, int r, int value) {
        if (r < l) return -1;
        int mid = l + ((r - l) >> 1);
        if (data[mid] > value) {
            return binarySearch2(data, l, mid - 1, value);
        } else if (data[mid] < value) {
            return binarySearch2(data, mid + 1, r, value);
        } else {
            return mid;
        }
    }

3、存在重复元素查找出现第一次相等的元素

 /**
     * 查找第一个等于某个元素的二分查找
     *
     * @param data
     * @return
     */

    public static int getBinarySearchFirst(int[] data, int value) {
        int l = 0;
        int r = data.length - 1;
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if (value < data[mid]) {
                r = mid - 1;
            } else if (value > data[mid]) {
                l = mid + 1;
            } else {
                //如果是第一个元素 或者说是它前面的元素是一个不等于它的数。
                if (mid == 0 || data[mid - 1] != value) {
                    return mid;
                } else {
                    r = mid - 1;
                }
            }
        }
        return -1;
    }

4、存在重复元素查找最后一个相等的元素

 /**
     * 查找最后一个元素等于某个元素的二分查找
     *
     * @param data
     * @param value
     * @return
     */
    public static int getBinarySearchLast(int[] data, int value) {
        int l = 0;
        int r = data.length - 1;
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if (value < data[mid]) {
                r = mid - 1;
            } else if (value > data[mid]) {
                l = mid + 1;
            } else {
                //如果是最右边的元素,或者右边的元素不等于value
                if (mid == data.length - 1 || data[mid + 1] != value) {
                    return mid;
                } else {
                    l = mid + 1;
                }
            }
        }
        return -1;
    }

5、 查找第一个大于等于给定值的元素


    /**
     * 查找第一个大于等于给定值的元素
     *
     * @param data
     * @param value
     * @return
     */
    public static int getBinarySearcFirst2(int[] data, int value) {
        int l = 0;
        int r = data.length - 1;
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            //如果这个数大于等于它的元素
            if (value >= data[mid]) {
                //如果mid 已经是最左边的元素了   或者说前面的元素已经下于某个元素了
                if (mid == 0 || data[mid - 1] < value) return mid;
                else {
                    l = mid + 1;
                }
            } else {
                r = mid - 1;
            }
        }
        return -1;
    }

6、查找最后一个小于等于给定值的元素

 /**
     * 查找最后一个小于等于给定值的元素
     *
     * @param data
     * @param value
     * @return
     */
    public static int getBinarySearcLast2(int[] data, int value) {
        int l = 0;
        int r = data.length - 1;
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if(data[mid]<=value){  //表示的是找到的元素
                if(mid==data.length-1||data[mid+1]>value){
                    return mid;
                }
                else{
                    l=mid+1;
                }
            }
        }
        return -1;
    }
}

三、总结

首先二分查找依赖的是顺序表结构,简单点说就是数组。

其次,二分查找针对的是有序数据。

最后,数据量太大也不适合二分查找

 

你可能感兴趣的:(数据结构学习)