java实现简单的二分查找,插值查找

前情提要:二分查找也叫折半查找,即在一个有序数组中通过每次将寻找的范围折半的方式来查找数据

解析即在代码里:


/**
 * @author hongda
 * 2020-04-09-17
 * 

* 使用二分查找的前提是该数组是有序的 */ public class BinarySearch { public static void main(String[] args) { int[] arr = {1, 8, 10, 89, 1234}; // int i = binarySearch(arr, 0, arr.length - 1, 89); // System.out.println("index=" + i) ArrayList list = binarySearch2(arr, 0, arr.length - 1, 1000); System.out.println("resIndexList" + list); } /** * @param arr 数组 * @param left 左边的索引 * @param right 右边的索引 * @param findVal 要查找的值 * @return 如果找到就返回下标, 没有找到就返回-1 */ public static int binarySearch(int[] arr, int left, int right, int findVal) { //设立一个中间值,这个值在二分查找里就是数组的中间 int mid = (left + right) / 2; int midVal = arr[mid]; //当left>right时,说明递归了整个数组,但是没有找到 if (left > right) { return -1; } //既然中间的这个数已经是不等于midVal了,那么把它抛弃也无可厚非 //所有下面的边界分别是mid+1和mid-1 if (findVal > midVal) { return binarySearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) { return binarySearch(arr, left, mid - 1, findVal); } //当找到这个值的时候,就返回其所在的下标 else { return mid; } } /** * 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到 * 1.在找到mid值时,不要马上返回 * 2.向mid索引值的左边扫描,将所有满足值的下标加入到集合ArrayList中 * 3.向mid索引值的右边扫描,将所有满足值的下标加入到集合ArrayList中 */ public static ArrayList binarySearch2(int[] arr, int left, int right, int findVal) { int mid = (left + right) / 2; int midVal = arr[mid]; //当left>right时,说明递归了整个数组,但是没有找到 if (left > right) { return new ArrayList(); } if (findVal > midVal) { return binarySearch2(arr, mid + 1, right, findVal); } else if (findVal < midVal) { return binarySearch2(arr, left, mid - 1, findVal); } else { ArrayList resIndexList = new ArrayList<>(); //向左查找 int temp = mid - 1; while (true) { if (temp < 0 || arr[temp] != findVal) { break; } resIndexList.add(temp); temp -= 1; } resIndexList.add(mid); //向右查找 temp = mid + 1; while (true) { if (temp > arr.length - 1 || arr[temp] != findVal) { break; } resIndexList.add(temp); temp += 1; } return resIndexList; } } }

插值查找:对二分查找的一种改进式算法,通过公式计算出尽可能接近的中间值,而非折半查找那样死板,从而减少递归的次数

解析附在代码中:

  /**
     * @param arr     数组
     * @param left    左边的索引
     * @param right   右边的索引
     * @param findVal 要查找的值
     * @return 如果找到就返回下标, 没有找到就返回-1
     */
    public static int insertValueSearch(int[] arr, int left, int right, int findVal) {
        //注意后面的条件必须存在,否则我们得到的mid可能越界,因为后面计算的中间值是有公式的
        if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
            return -1;
        }
        //插值算法公式
        int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
        int midVal = arr[mid];
        //下面的就和二分查找法思维一致
        if (findVal > midVal) {
            return insertValueSearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {
            return insertValueSearch(arr, left, mid - 1, findVal);

        }else {
            return mid;
        }
    }
}

 

你可能感兴趣的:(算法)