Interpolation Search 插值搜索算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jxw167/article/details/72844776

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

再给读者介绍一种算法插值算法,给定n个均匀分布值arr []的排序数组,写一个函数来搜索数组中的特定元素x。我们先比较一下各种搜索算法实现该算法的复杂度,线性搜索在O(n)时间内找到元素,跳跃搜索采用O(√n)时间,二进制搜索取O(Log n)时间。

插值搜索是对实例的二分查找搜索的改进,其中排序数组中的值均匀分布。 二分查找搜索总是转到中间元素来检查。 另一方面,根据正在搜索的键的值,插值搜索可以去不同的位置例如,如果键的值更接近最后一个元素,则插值搜索可能会朝向端部开始搜索。

要找到要搜索的位置,它使用以下公式。

// The idea of formula is to return higher value of pos
// when element to be searched is closer to arr[hi]. And
// smaller value when closer to arr[lo]
pos = lo + [ (x-arr[lo])*(hi-lo) / (arr[hi]-arr[Lo]) ]

arr[] ==> Array where elements need to be searched
x     ==> Element to be searched
lo    ==> Starting index in arr[]
hi    ==> Ending index in arr[]

插值算法与上述分区逻辑相同。
步骤1:在循环中,使用探针位置公式计算“pos”的值。
步骤2:如果是匹配项,返回项的索引,然后退出。
步骤3:如果项小于arr [pos],计算左子阵列的探针位置
否则在右侧子阵列中计算是否相同
步骤4:重复,直到发现匹配或子数组减少为零。

先给读者介绍一下使用C语言实现算法代码:

#include<stdio.h>
 
// If x is present in arr[0..n-1], then returns
// index of it, else returns -1.
int interpolationSearch(int arr[], int n, int x)
{
    // Find indexes of two corners
    int lo = 0, hi = (n - 1);
 
    // Since array is sorted, an element present
    // in array must be in range defined by corner
    while (lo <= hi && x >= arr[lo] && x <= arr[hi])
    {
        // Probing the position with keeping
        // uniform distribution in mind.
        int pos = lo + (((double)(hi-lo) /
              (arr[hi]-arr[lo]))*(x - arr[lo]));
 
        // Condition of target found
        if (arr[pos] == x)
            return pos;
 
        // If x is larger, x is in upper part
        if (arr[pos] < x)
            lo = pos + 1;
 
        // If x is smaller, x is in lower part
        else
            hi = pos - 1;
    }
    return -1;
}
 
// Driver Code
int main()
{
    // Array of items on which search will
    // be conducted.
    int arr[] =  {10, 12, 13, 16, 18, 19, 20, 21, 22, 23,
                  24, 33, 35, 42, 47};
    int n = sizeof(arr)/sizeof(arr[0]);
 
    int x = 18; // Element to be searched
    int index = interpolationSearch(arr, n, x);
 
    // If element was found
    if (index != -1)
        printf("Element found at index %d", index);
    else
        printf("Element not found.");
    return 0;
}
另外给读者展示一下java实现的代码:

class Test
{
    // Array of items on which search will
    // be conducted.
    static int arr[] = new int[]{10, 12, 13, 16, 18, 19, 20, 21, 22, 23,
                                         24, 33, 35, 42, 47};
     
    // If x is present in arr[0..n-1], then returns
    // index of it, else returns -1.
    static int interpolationSearch(int x)
    {
        // Find indexes of two corners
        int lo = 0, hi = (arr.length - 1);
      
        // Since array is sorted, an element present
        // in array must be in range defined by corner
        while (lo <= hi && x >= arr[lo] && x <= arr[hi])
        {
            // Probing the position with keeping
            // uniform distribution in mind.
            int pos = lo + (((hi-lo) /
                  (arr[hi]-arr[lo]))*(x - arr[lo]));
      
            // Condition of target found
            if (arr[pos] == x)
                return pos;
      
            // If x is larger, x is in upper part
            if (arr[pos] < x)
                lo = pos + 1;
      
            // If x is smaller, x is in lower part
            else
                hi = pos - 1;
        }
        return -1;
    }
   
    // Driver method 
    public static void main(String[] args) 
    {
         int x = 18; // Element to be searched
         int index = interpolationSearch(x);
          
         // If element was found
         if (index != -1)
            System.out.println("Element found at index " + index);
         else
            System.out.println("Element not found.");
    }
}
运行输出结果:

Element found at index 4
时间复杂性:如果元素均匀分布,则O(log log n)),在最坏的情况下可能需要O(n)。
辅助空间:O(1)







没有更多推荐了,返回首页