插值查詢演算法
阿新 • • 發佈:2020-10-18
插值查詢演算法原理
- 插值查詢演算法類似於二分查詢,不同的是插值查詢每次從自適應mid處開始查詢
- 將折半查詢中的求mid索引的公式 \(mid=\frac{left+right}{2}=low+\frac{1}{2}(left+right)\) 改成 \(mid=low+\frac{findVal-arr[left]}{arr[right]-arr[left]}(right-left)\)
舉例說明插值查詢演算法
程式碼實現
程式碼實現返回查詢到的第一個索引
public class InsertValSearch { public static void main(String[] args) { int[] arr = {1, 8, 10, 89, 1000, 1234}; int index = insertValSearch(arr, 0, arr.length - 1, 1000); System.out.println("index = "+index); } /** * @param arr 陣列 * @param left 左邊的下標 * @param right 右邊的下標 * @param findVal 待查詢的值 * @return 返回找到的第一個索引 */ private static int insertValSearch(int[] arr, int left, int right, int findVal) { if (findVal < arr[left] || findVal > arr[right] || left > right) { return -1; } int mid = left + (findVal - arr[left]) / (arr[right] - arr[left]) * (right - left); if (findVal < arr[mid]) { return insertValSearch(arr, left, mid - 1, findVal); } else if (findVal > arr[mid]) { return insertValSearch(arr, mid + 1, right, findVal); }else { return mid; } } }
返回查詢到的所有下標
public class InsertValSearch { public static void main(String[] args) { int[] arr = {1, 8, 10, 89, 1000,1000, 1234}; List<Integer> indexList = insertValSearch2(arr, 0, arr.length - 1, 1000); System.out.println("indexList = "+indexList); } /** * @param arr 陣列 * @param left 左邊的下標 * @param right 右邊的下標 * @param findVal 待查詢的值 * @return 返回找到的所有值的下標 */ private static List<Integer> insertValSearch2(int[] arr, int left, int right, int findVal) { if (findVal < arr[left] || findVal > arr[right] || left > right) { return new ArrayList<Integer>(); } int mid = left + (findVal - arr[left]) / (arr[right] - arr[left]) * (right - left); List<Integer> indexList = new ArrayList<>(); if (findVal < arr[mid]) { return insertValSearch2(arr, left, mid - 1, findVal); } else if (findVal > arr[mid]) { return insertValSearch2(arr, mid + 1, right, findVal); } else { // 這裡需要返回所有的下標,所以需要對找到的一個下標進行向左和向右的遍歷 int temp = mid - 1; while (true) { // 向左遍歷 if (temp < 0 || arr[temp] != findVal) { break; } indexList.add(temp); temp -= 1; } indexList.add(mid); temp = mid + 1; while (true) { //向右遍歷 if (temp > arr.length - 1 || arr[temp] != findVal) { break; } indexList.add(temp); temp += 1; } return indexList; } }