算法與數據結構-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 二分法需要六次遞歸,而插值查詢只需要一次。  但是插值查詢的效率不一定比二分查找效率高。如果數組元素跳躍性大,不夠連續,會出現插值查詢效率比二分查找效率低的情況發生。

 

注意:插值查詢和二分查找最大的區別就是獲取"中間值"的算法不同!!!

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