插值查询是以二分查询优化方案的身份存在的。
从字(词)典查找“阿”或者“zip”,相信不会有人会从正中间开始查吧,而是直接翻到接近这个词在字典中的大致页数。
比如在一个有序的从小到大并且数值均匀分布的数组中查询一个接近数组最大边界处的比较大数的数时,我们首先想到就是从数组下标大的大方开始查询。所以这就是插值查询方式出现的理由。
借鉴上篇博对二分查找的介绍:有序表查询之一:java实现整型数组二分查找。在查找实现代码的binarySearch方法中代码处:
int middle = (int) Math.ceil((double)(hig + low) / 2);
进行等式变换可得:
int middle = low + (int) Math.ceil((double)(hig - low) / 2);
现在继续对这个1 / 2进行变换,又得:
也就是将1 / 2 转换为 :int middle = low + (int) Math.ceil((double)(hig - low) * (key - ints[low]) / (ints[hig] - ints[low]));
(key - ints[low]) / (ints[hig] - ints[low])
该如何理解呢?加入存在以下有序数组,low = 0, hig = 10, 那么a[low] = 0, a[hig] = 99,如查找其中的16或者24,根据二分法都要进行4次查询,如果(查询16时)使用(key - a[low]) / (a[hig] - a[low]) 其值约为0.1616,即middle约等于 0 + 2得2,也就是只需一次就完成了查找,24同样也只需要一次。
int intArr = {0, 1, 16, 24, 35, 47, 59, 62, 73, 88, 99};
跟二分查找法进行比较后发现,其算法复杂度也为O(logn)。但二者的使用范围依然是有区别的,在表界较宽的情况下显得尤为明显,不然插值查找也就没有存在必要了。
- 组成表的数值在表中均匀分布,插值优于二分
- 组成表的数值在表中分布极度不均,二分优于插值