22_插值查找
一、原理介绍
-
插值查找算法由二分查找算法而来,但插值查找进行了改进,每次从自适应mid处开始查找
-
二分查找的求mid索引公式 ,low表示左边索引left,high表示右边索引right,key表示之前提到的 findVal
int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]);/*插值索引*/
在代码中体现为:
int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left]);
- 举例说明插值查找算法 的实际使用
插值查找算法的 举例说明
数组 arr = [1, 2, 3, ......., 100]
假如我们需要查找的值 1
使用二分查找的话,我们需要多次递归,才能找到 1
使用插值查找算法
int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])
int mid = 0 + (99 - 0) * (1 - 1)/ (100 - 1) = 0 + 99 * 0 / 99 = 0
比如我们查找的值 100
int mid = 0 + (99 - 0) * (100 - 1) / (100 - 1) = 0 + 99 * 99 / 99 = 0 + 99 = 99
二、代码实现
import java.util.Arrays;
public class InsertValueSearch {
public static void main(String[] args) {
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = i + 1;
}
//System.out.println(Arrays.toString(arr));
int index = insertValueSearch(arr, 0, arr.length - 1, 1);
System.out.println("index = " + index);
}
//编写插值查找算法(同样要求数组有序)
/**
* @param arr 数组
* @param left 左索引
* @param right 右索引
* @param findVal 查找值
* @return 若找到就返回对应下标,若未找到则返回-1
*/
public static int insertValueSearch(int[] arr,int left,int right, int findVal){
//System.out.println("查找次数~~");
//注意:findVal < arr[0] 和 findVal > arr[arr.length - 1] 是必须的 否则mid可能越界
if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]){
return -1;
}
//求出mid
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
int midVal = arr[mid];
if (findVal > midVal){
//向右递归
return insertValueSearch(arr,mid + 1,right,findVal);
}else if(findVal < midVal){
//向左递归
return insertValueSearch(arr,left,mid - 1,findVal);
}else {
return mid;
}
}
}
三、注意事项
- 当数据量较大且关键字(key)分布较平均的情况下,采用插值查找的速度要快于二分查找。
- 当关键字(key)分布方差较大时,插值查找方法速度不如二分查找。