插值查找

在介绍插值查找之前,首先考虑一个问题,为什么二分查找算法中一定是折半,而不是折四分之一,或者折更多呢?
打个比方,在英文字典里面查“apple”,你下意识翻开字典是翻前面的书页还是后面的书页呢?如果再查“zoo”,又该怎么查呢?很显然,这两个单词绝对不会从中间开始查起,而是有一定目的地从前或从后开始查;
同样地,比如要在取值范围1~10000之间100个元素从小到大均匀分布的数组中查找5,我们自然会考虑从数组下标较小的开始查找;
经过以上分析,二分查找这种查找方式,不是自适应的(也就是傻瓜式的),二分查找中查找点计算如下:
mid = (low + high)/2 = low + 1/2 * (high - low);
通过类比,可以将查找的点改进为如下:
mid = low + ((key - arr[low])/(arr[high] - arr[low])) * (high - low);
也就是将上述的比例参数1/2改进为自适应的,根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数;

基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,插值查找也属于有序查找。

注:对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比二分查找算法要好得多。

复杂度分析:时间复杂度O(log2^(log2^n))。

代码示例:
public class Test {

    public static void main(String[] args) {
        
        int[] arr = {1, 2, 3, 6, 8, 9};
        System.out.println(binary_Search(arr, 8));
    }
    public static int binary_Search(int[] arr, int num) {
        int high = arr.length - 1;
        int low = 0;
        int mid;
        while(low < high) {
            mid = low + ((num - arr[low])/(arr[high] - arr[low])) * (high - low);
            if(arr[mid] > num) {
                high = mid - 1;
            } else if (arr[mid] < num) {
                low = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

猜你喜欢

转载自www.cnblogs.com/yuanfei1110111/p/10205065.html