插值查找的公式推导
插值查找的数学逻辑来自于等差数列
插值查找的基本思想 基于二分查找算法,将查找点的选择改进为自使用选择,可以提高查找效率
插值查找的细节 对于表长较长,而关键字分布又比较 均匀 的查找表而言,插值查找算法的平均性能要不二分查找好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择
插值查找的的代码跟二分查找的类似,只需要修改一下mid的计算方式即可
二分查找中mid的查找公式是
m
i
d
=
l
o
w
+
1
/
2
∗
(
h
i
g
h
−
l
o
w
)
;
mid=low+1/2*(high-low);
mid=low+1/2∗(high−low);
这个公式就是简单的确定中间值
而插值查找中的mid的查找公式是
m
i
d
=
l
o
w
+
(
k
e
y
−
a
[
l
o
w
]
)
/
(
a
[
h
i
g
h
]
−
a
[
l
o
w
]
)
∗
(
h
i
g
h
−
l
o
w
)
,
mid=low+(key-a[low])/(a[high]-a[low])*(high-low),
mid=low+(key−a[low])/(a[high]−a[low])∗(high−low),
这个公式主要是用等差数列的方法进行自使用的查找
等差数列在mid公式中的运用
插值查找的主要应用场景是比较均匀的递增或递减的数据
如果是完全均匀的数据情况下,那就类似数学中的等差数列
数据的分布越接近等差数列,所需要的次数就会越少
那就用数学的方式将公式进行推理
等差数列的两个主要公式是
a
n
=
a
1
+
(
n
−
1
)
∗
d
a_{n}=a_{1}+(n-1)*d
an=a1+(n−1)∗d
S n = a 1 ∗ n + n ∗ ( n − 1 ) 2 = n ∗ ( a 1 + a n ) 2 S_{n}=a_{1}*n+\frac{n*(n-1)}{2}=\frac{n*(a_{1}+a_{n})}2 Sn=a1∗n+2n∗(n−1)=2n∗(a1+an)
d = ( a n − a 1 ) n − 1 d=\frac{(a_{n}-a_{1})}{n-1} d=n−1(an−a1)
将这些公式转化为数组的形式的话就会是以下形式
d
=
a
[
h
i
g
h
]
−
a
[
l
o
w
]
h
i
g
h
−
l
o
w
d=\frac{a[high]-a[low]}{high-low}
d=high−lowa[high]−a[low]
a [ h i g h ] = a [ l o w ] + ( h i g h + l o w ) ∗ d a[high]=a[low]+(high+low)*d a[high]=a[low]+(high+low)∗d
a[high]为数组中的最大值
a[low]为数组中的最小值
high为最大值在数组中对应的下标
low为最小值在数组中对应的下标
假设要求的数据为key并且在这些数据中存在,那么就可以根据公式求出位置
因为要求的是key的位置,所以可以联想到数组中下标和等差数列中的第n项
n
=
a
n
−
a
1
d
+
1
n=\frac{a_{n}-a_{1}}{d}+1
n=dan−a1+1
因为等差数列的第n项是从1开始的,而数组的下标是从0开始的,所以可以将上式转化成以下形式
n
=
k
e
y
−
a
[
l
o
w
]
a
[
h
i
g
h
]
−
a
[
l
o
w
]
h
i
g
h
−
l
o
w
+
l
o
w
n=\frac{key-a[low]}{\frac{a[high]-a[low]}{high-low}}+low
n=high−lowa[high]−a[low]key−a[low]+low
再将上述式子进行简化
n
=
l
o
w
+
k
e
y
−
a
[
l
o
w
]
a
[
h
i
g
h
]
−
a
[
l
o
w
]
∗
(
h
i
g
h
−
l
o
w
)
n=low+\frac{key-a[low]}{a[high]-a[low]}*(high-low)
n=low+a[high]−a[low]key−a[low]∗(high−low)
再将这个式子与插值查找的式子进行比较,可以发现两者一致,这就说明这个公式是来自于类似等差数列的一种结构,并且可以看出来,通过这个式子可以看出,如果数据在数组中而且数组分布类似等差数列的规范程度的话,可以只通过一次就可以查找到位置
如果要查找的key不在等差数列这样的数组中,或者这个数组的数据分布的不是十分均匀,那么就需要用着公式进行多次查找了