算法与数据结构-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 二分法需要六次递归,而插值查询只需要一次。 但是插值查询的效率不一定比二分查找效率高。如果数组元素跳跃性大,不够连续,会出现插值查询效率比二分查找效率低的情况发生。
注意:插值查询和二分查找最大的区别就是获取"中间值"的算法不同!!!