思路分析
-
插值查找是基于二分查找进行的优化,基本思路与二分查找的一致,只是在进行划分时mid的确定不同:
==>插值查找采取的是一种 自适应mid的计算方法:
mid = left + (right - left) * (findval - arr[left])/(arr[right] - arr[left])
含义:根据findVal 与 arr[left]的差值,在arr[right] - arr[left]中所占据的比例,来确定findVal在待查找序列中可能对应的下标值
---->由此也可以看出,插值查找主要适用于:数组元素(待查找序列)的值分布比较均匀的情况下 -
需要注意的是:插值查找进行自适应mid计算有一个前提:
对于输入的findVal过大或过小,都可能造成数组下标越界
==>即,findVal的值,应该在arr[]的范围内,才有进行插值查找的意义
---->
应该加上判断条件:
if(findVal < arr[0] || findVal > arr[arr.length-1])
如果满足该条件,直接return -1;
代码实现
public static int insertValueSearch(int[] arr,int left,int right,int findVal) {
//递归完待查找序列,但是没有找到findVal,结束递归
//注意:如果findVal 远小于 arr[0] ,或者findVal 远大于 arr[arr.lengtth-1]====>可能会导致求出来的mid下标越界
if(left > right || findVal < arr[0] || findVal > arr[arr.length-1]) {
//要对于输入的findVal进行特殊情况的处理,否则findVal过大或过小,都可能造成数组下标越界
return -1;
}
//没有递归完待查找序列的时候
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;
}
}
总结
1、对于数据量较大,且关键字分布均匀的查找表来说,采用插值查找,速度比较快;
2、在关键字分布不均匀的情况下,插值查找 不一定会比 折半查找快。
技术的突飞猛进往往是自然发生的。 你在某个夜晚苦熬一个知识点时, 不会觉得自己突飞猛进; 只有在多年后的某日, 熟练地给别人讲解这个知识点后, 内心才会小小地波动一下, 猛然忆起当年深夜中的青灯一盏。