插值查詢
二分查找雖然快捷,但是每次折半查找,查找過程不具有動態性,究其原因是由於待查找元素每次與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 二分法需要六次遞歸,而插值查詢只需要一次。 但是插值查詢的效率不一定比二分查找效率高。如果數組元素跳躍性大,不夠連續,會出現插值查詢效率比二分查找效率低的情況發生。
注意:插值查詢和二分查找最大的區別就是獲取"中間值"的算法不同!!!