图解查找算法之插值查找(带源码)
在前面我们了解了二分查找,就是把一个集合的元素一分为二,用中间值和目标查找值相比较,直到要查找的值和中间值相等,则表示查找成功,反之表示不成功。为什么这里会再次提到二分查找呢?事实上,插值查找是二分查找的升级版。
用一个很简单的例子就可以把插值查找解释的很清楚。在字典里面找”boy”这个单词时,我们肯定不会从第一页开始找,而是从首字母为b的位置开始查找,然后再找到第二个字母在字母表中的位置,找到对应的位置后,重复这个过程,这样就可以快速的找到目标单词。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkCERg64-1652934345859)(https://pics6.baidu.com/feed/f9198618367adab4e470a3f84344b8168601e400.png?token=d0611e5c954e4e9e457ceb91d266becc)]
接下来就介绍一下插值查找吧。
我们知道的的二分查找有一个必要的前提,必须是有序的数组才可以进行二分查找,同样插值查找也只能用于一个呈线性增长的有序数组中。
首先我们在数组中找到左边索引low和右边的索引high,目标查找值key
在二分查找中mid表示数组的中间值,而插值查找中mid表示一个自适应处,插值查找每次是从自适应mid处开始查找,mid的计算方式为:low + (key – arr[low]) / (arr[high] – arr[low]) * (high - low);在这里mid表示的就是目标值key在序列总的所占比。
插值公式:
插值 = (设算数 - 最小数) / (最大数 - 最小数)
搜索键值 = left + parseInt( ( key - data[ left ] ) / ( data[ right ] - data[ left ] ) ) * ( right - left ) )
插值搜索之算法与二分搜索算法几乎完全相同,差别在:
- 二分搜索法:猜测键值在中间位置(middle)
- 插值搜索法:用插值公式计算键值位置
代码
package com.ma.select;
public class InsertSelect {
public static void main(String[] args) {
int[] array = new int[]{3,6,8,15,16,18,28};
System.out.println(insertselect(array,0,array.length-1,18));
}
public static int insertselect(int[] array,int left,int right,int target){
//防止数组越界
if (left>right || target>array[right] || target<array[left]){
return -1;
}
// 求出mid即中间位置索引, 自适应
int mid = left + (right - left) * ((target - array[left]) / (array[right] - array[left]));
int midvalue = array[mid];//中间位置索引的值
if (midvalue > target){//向右递归
return insertselect(array,left,mid-1,target);
}
if (midvalue < target){//向左递归
return insertselect(array,mid+1,right,target);
}
if (midvalue == target){
return mid;
}
return -1;
}
}
ue == target){
return mid;
}
return -1;
}
}