算法原理
算法基于二分查找(binary search) 演变而成,拥有二分查找时间复制度小的优点,而思想也几乎是继承了二分查找。
相比 斐波那契查找 ,插值查找一样有特殊的middle选取方式:

该公式即为middle点的选取方式,而在 key < A[middle] 时则将high取为middle - 1,这点与二分查找同理,key > A[middle]时则同理将 low 取为 middle + 1
但这有一个问题,在清华大学邓老师的课中有一个很不错的例子,当数组/向量的数据为
int a[19] = { 5,10,12,14,26,31,38,39,42,46,49,51,54,59,72,79,82,86,92 }
low和middle的计算很容易陷入10与11的死循环,按照公式的判断流程如下(引自清华大学邓老师数据结构与算法课PPT)
因此在使用插值查找时 ,要用某些方法防止数据导致的死循环,这是网上很多博客没提到的,而防止的方法很多,我的代码则用的是针对这一组数据
算法代码(简易)
include<iostream>
using namespace std;
int Interpolation_search(int *a, int search_value, int low, int high)
{
if (low > high)
return -1;
int lo = low, hi = high;
int mid = lo + (hi - lo)*((search_value - a[lo]) / (a[hi] - a[lo]));
if(mid>=10)
reurn -1;
if (a[mid] < search_value)
return Interpolation_search(a, search_value, mid + 1, hi);
else if (search_value < a[mid])
return Interpolation_search(a, search_value, lo, mid - 1);
else if (a[mid] == search_value)
return mid + 1;
}
int InterpolationSearch(int *A, int e, int low, int high)
{
while (low < high)
{
int mid = low + (high - low - 1)*(e - A[low]) / (A[high - 1] - A[low]);
if (mid >= 10) //在这里防止死循环退出
return -1;
if (e < A[mid])
high = mid;
else if (e > A[mid])
low = mid + 1;
else
return mid;
}
return -1;
}
int main()
{
int a[19] = { 5,10,12,14,26,31,38,39,42,46,49,51,54,59,72,79,82,86,92 };
// cout<<Interpolation_search(a,50,0,18)<<endl;;
cout << InterpolationSearch(a, 50, 0, 18);
cout << endl;
return 0;
}
优缺点
插值查找限制条件也是其查找时间成本为 o(logn) 的原因之一,要求数据有序且分布均匀,分布均匀可以理解为每个数据在某个区间内的某个恰当位置(可见下图,图源依旧为清华大学邓老师的课)。当需要查找的数据源极大的时候,插值查找可以很大程度上缩短所需的时间,而在极小的数据源中,顺序查找更优,二分查找以及斐波那契查找则相较占中些(个人理解),因此查找更需要的是正确的选择,避免小题大做,以及最重要的是有序数据

本文深入探讨了插值查找算法的原理,展示了其基于二分查找的改进之处,特别是在数据有序且分布均匀的情况下,查找效率可达O(logn)。文章通过实例解释了如何避免特定数据集引起的死循环,并提供了简易的算法实现代码。
1315

被折叠的 条评论
为什么被折叠?



