算法与数据结构-06-插值查询

插值查询

二分查找虽然快捷,但是每次折半查找,查找过程不具有动态性,究其原因是由于待查找元素每次与mid中间值进行比较,但中间值的获取算法是固定的,即(left+right)/ 2 ,如果获取中间值得算法是动态的或许会更高效,这就是插值查询。

 

 

package day05;

import java.util.Arrays;

/**
 * 二分查找进阶【插值查找】
 * 插值寻找公式:int mid=left+(right-left)*(findVal-arr[left])/(arr[right]-arr[left])
 */
public class InterpolationSearch {

    private static int binarySearchNumber = 0;
    private static int interpolationSearchNumber = 0;

    public static void main(String[] args) {
        int[] array = new int[100];
        for (int i = 0; i < array.length; i++) {
            array[i] = i;
        }
//        System.out.println(Arrays.toString(array));

        // 测试二分查找 查找99需要递归多少次
        int binarySearchIndex = binarySearch(99, 0, array.length-1, array);
        System.out.println(binarySearchIndex);


        System.out.println("--------------------------------------------");

        // 测试插值查找 查找99需要递归多少次
        int interpolationSearchIndex = interpolationSearch(99, 0, array.length-1, array);
        System.out.println(interpolationSearchIndex);

    }

    /**
     * 插值查找
     * 使用条件:数组数据有序,数据相对连续
     *
     * @param findVal
     * @param left
     * @param right
     * @param arr
     * @return
     */
    public static int interpolationSearch(int findVal, int left, int right, int[] arr) {
        System.out.println("插值查询 查找" + findVal + "递归" + (++interpolationSearchNumber) + "次~");

        if (left > right || findVal < arr[left] || findVal > arr[right]) {
            return -1;
        }

        int mid = left + (right - left) * ((findVal - arr[left]) / (arr[right] - arr[left]));
        int midVal = arr[mid];
        if (findVal < midVal) {
            right = mid - 1;
            return interpolationSearch(findVal, left, right, arr);
        } else if (findVal > midVal) {
            left = mid + 1;
            return interpolationSearch(findVal, left, right, arr);
        } else {
            return mid;
        }

    }

    /**
     * 二分查找
     * 适应条件:数组有序
     *
     * @param findVal
     * @param left
     * @param right
     * @param arr
     * @return
     */
    public static int binarySearch(int findVal, int left, int right, int[] arr) {
        System.out.println("二分查询 查找" + findVal + "递归" + (++binarySearchNumber) + "次~");

        if (left > right || findVal < arr[left] || findVal > arr[right]) {
            return -1;
        }

//        int mid = left + (1/2)*(right - left) ;
        int mid = left + (right - left) / 2;
//        int mid = (left+right)/2;
        int midVal = arr[mid];
        if (findVal < midVal) {
            right = mid - 1;
            return binarySearch(findVal, left, right, arr);
        } else if (findVal > midVal) {
            left = mid + 1;
            return binarySearch(findVal, left, right, arr);
        } else {
            return mid;
        }
    }

}

结论:经过对比 查询99 二分法需要六次递归,而插值查询只需要一次。  但是插值查询的效率不一定比二分查找效率高。如果数组元素跳跃性大,不够连续,会出现插值查询效率比二分查找效率低的情况发生。

 

注意:插值查询和二分查找最大的区别就是获取"中间值"的算法不同!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章