插值查找算法

目录

解题思路

减治法

折半查找

插值查找

MId的计算

例1

缺点

例2

具体实现

资料来源


解题思路

首先想要了解插值查找需要了解折半查找,而他们又都共属于减治法。

减治法

就是将一个大的问题,分解成若干个小的问题,然后解决其中的一个小的问题,在建立起其之间的联系,以求得最后的答案。

折半查找

由于本文主要是讲述插值算法,对折半算法就进行一个概述:折半查找,又叫二分法查找,就是将搜索区域每次减小一半的查找,以此来降低搜索难度

插值查找

插值查找是改进的折半查找,将原有的50%改成了按特定比例的查找。

我们来举一个例子:

假设一个字典是均匀分布的(a,b,c,d每个字母开头的单词的页数都一样),我们需要找到D这个字母开头的词。我们是不会从中间进行查找,我们会从大概4/26的附近位置。这就是插值查找的主要实现思路。

以在升序序列中查找目标元素为例,插值查找算法的实现思路是: ·

1.初始状态下,将整个序列作为搜索区域(假设为 [Begin, End]);

2.找到搜索区域内的插值元素(假设所在位置为 M),和目标元素进行比对。如果相等,则搜索成功;如果插值元素大于目标元素,表明目标元素位于插值元素的左侧,将 [Begin, M-1] 作为新的搜素区域;反之,若插值元素小于目标元素,表明目标元素位于插值元素的右侧,将 [M+1, End] 作为新的搜素区域;

3.重复执行第二步,直至找到目标元素。如果搜索区域无法再缩小,且区域内不包含任何元素,表明整个序列中没有目标元素,查找失败。

MId的计算

那么这个M的值是如何计算出来的呢?

在折半查找中: Mid = (Begin+End)/2 =Begin+1/2(End-begin)

Mid = Begin + ( (X - A[Begin]) / (A[End] - A[Begin]) ) *(End - Begin)

Mid:计算得出的元素的位置;

End:搜索区域内最后一个元素所在的位置;

Begin:搜索区域内第一个元素所在的位置;

X:要查找的目标元素                  

A[]:表示整个待搜索序列。

对比得出公式是将1/2改为了( (X - A[Begin]) / (A[End] - A[Begin]) )

(X - A[Begin])是得到了插值元素和搜索区域内第一个元素的差值(类比D在字母表中为4-0)

(A[End] - A[Begin]) 得到了整个搜索区域的差值(类比于字母表中有26个字母26-0)

例1

1

2

3

4

5

6

7

8

9

10

 在这样一个数组中我们需要找到2

带入公式Mid = Begin + ( (X - A[Begin]) / (A[End] - A[Begin]) ) *(End - Begin)

        Mid =     0 +     ( ( 2    -    1 ) / (    10     -        1       ) ) * (   9   -   0 )     = 1

而得到的一正是目标元素2的值,在这个例子中明显插值查找的效率比折半查找的高得多

缺点

例2

1

2

3

4

5

18

19

21

77

322

888

1025

1527

2229

Mid = Begin + ( (X - A[Begin]) / (A[End] - A[Begin]) ) * (End - Begin)

Mid =     0 +     ( ( 77 - 1 ) / (   2229 -        1       ) ) *(   13   -   0   )      = 0.44--1

Mid =     1 +     ( ( 77 - 2 ) / (   2229 -        2      ) ) *(   13   -   1   )      = 1.40--2 ……………

看得出每次搜索区域只减少了1,很明显在此数组中插值查找远不如折半查找的效率高。

从而我们得到:当有序序列中的元素呈现均匀分布时,插值查找算法的查找效率要优于折半查找算法;反之,如果有序序列不满足均匀分布的特征,插值查找算法的查找效率不如折半查找算法。 所谓均匀分布,是指序列中各个相邻元素的差值近似相等。例如,{10, 20, 30, 40, 50} 就是一个均匀分布的升序序列,各个相邻元素的差值为 10。再比如 {100, 500, 2000, 5000} 是一个升序序列,但各相邻元素之间的差值相差巨大,不具备均匀分布的特征。

总的来说,有序+均匀分布是插值查找的最大缺点

具体实现

int interpolation_search(int* arr, int begin, int end, int x)
{
    int mid = 0;
    if (begin > end) { return -1; }
    if (begin == end) {
        if (x == arr[begin]) { return begin; }
        return -1;
    }
    mid = begin + ((x - arr[begin]) / (arr[end] - arr[begin]) * (end - begin));
    if (x == arr[mid]) { return mid; }
    if (x < arr[mid]) { return interpolation_search(arr, begin, mid - 1, x); }
    else              { return interpolation_search(arr, mid + 1, end, x); }
}

插值算法的时间复杂度:

 第一次假设搜索区域折为:N/m1

 则第二次搜索区域折为:N/(m1*m2)

第三次:N/(m1*m2*m3)

…………

假设当第n次搜索区域只剩下一个元素,即数列已被搜索完成即:N/(m1*m2*m3*…*mn)=1

那我们得到n的值为以m1*m2*m3*...mn为底N的对数

则O(n)=log2N

资料来源

https://blog.csdn.net/huanghanqian/article/details/79088171

https://www.bilibili.com/video/BV1nY4y1N7v1/?spm_id_from=333.337.search-card.all.click&vd_source=05aa685c08d081347bed6210640e9f07 https://blog.csdn.net/qq_29542611/article/details/79392661

http://c.biancheng.net/algorithm/interpolation-search.html

https://blog.csdn.net/glassesone/article/details/106910155

https://developer.aliyun.com/article/853262

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值