• 12、【查找算法】插值查找


    插值查找

      在介绍插值查找之前,首先考虑一个新问题,为什么上述算法一定要是折半,而不是折四分之一或者折更多呢?
      打个比方,在英文字典里面查“apple”,你下意识翻开字典是翻前面的书页还是后面的书页呢?如果再让你查“zoo”,你又怎么查?很显然,这里你绝对不会是从中间开始查起,而是有一定目的的往前或往后翻。
      同样的,比如要在取值范围1 ~ 10000 之间 100 个元素从小到大均匀分布的数组中查找5, 我们自然会考虑从数组下标较小的开始查找。
      经过以上分析,折半查找这种查找方式,不是自适应的(也就是说是傻瓜式的)。二分查找中查找点计算如下:
      mid=(low+high)/2, 即mid=low+1/2*(high-low);
      通过类比,我们可以将查找的点改进为如下:
      mid=low+((key-a[low])/(a[high]-a[low])) * (high-low),
      也就是将上述的比例参数1/2改进为自适应的,根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。
      基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。
      注:对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。
      复杂度分析:查找成功或者失败的时间复杂度均为O(log2(log2n))。
    C++实现源码:
     1 //插值查找
     2 #include <iostream>
     3 #include <stdlib.h>
     4 #include <ctime>
     5 
     6 using namespace std;
     7 
     8 #define MAX 100
     9 //数组输入
    10 void input(int *arr)
    11 {
    12     srand((unsigned)time(NULL));
    13     for(int i = 0; i < MAX; i++)
    14     {
    15         arr[i] = rand()%100;
    16     }
    17 }
    18 //数组输出
    19 void output(int *arr)
    20 {
    21     for(int i = 0; i < MAX; i++)
    22     {
    23         cout << arr[i] << "  ";
    24         if(0 == i % 10)
    25             cout << endl;
    26     }
    27     cout << endl;
    28 }
    29 //快速排序
    30 void quickSort(int *arr, int l, int h)
    31 {
    32     if(l < h)
    33     {
    34         int low, high, tmp;
    35         low = l;
    36         high = h;
    37 
    38         tmp = arr[l];//选择基准值
    39         //将数组按照基准值分为两部分
    40         while(low < high)
    41         {
    42             while(low < high && arr[high] > tmp)
    43                 high--;
    44             if(low < high)
    45                 arr[low++] = arr[high];
    46             while(low < high && arr[low] < tmp)
    47                 low++;
    48             if(low < high)
    49                 arr[high--] = arr[low];
    50         }
    51         arr[low] = tmp;
    52         //递归排序
    53         quickSort(arr, l, low-1);
    54         quickSort(arr, low+1, h);
    55     }
    56 }
    57 //插值查找
    58 int insertionSearch(int *arr, int value, int low, int high)
    59 {
    60     //相比
    61     int mid = low + ((value - arr[low])/(arr[high] - arr[low]))*(high - low);
    62 
    63     if(arr[mid] == value)
    64         return mid;
    65     if(arr[mid] > value)
    66         return insertionSearch(arr, value, low, mid-1);
    67     if(arr[mid] < value)
    68         return insertionSearch(arr, value, mid+1, high);
    69 }
    70 
    71 int main()
    72 {
    73     int x, pos, num[MAX];
    74     input(num);
    75 
    76     cout << "sort before:" << endl;
    77     output(num);
    78     quickSort(num, 0, MAX-1);
    79     cout << "sort after:" << endl;
    80     output(num);
    81 
    82     cout << "Enter find num : ";
    83     cin >> x;
    84 
    85     pos = insertionSearch(num, x, 0, MAX-1);
    86 
    87     if(pos)
    88         cout << "OK!" << x << "is found in pos : " << pos << endl;
    89     else
    90         cout << "Sorry!" << x << "is not found in num" << endl;
    91 
    92     return 0;
    93 }
  • 相关阅读:
    June. 26th 2018, Week 26th. Tuesday
    June. 25th 2018, Week 26th. Monday
    June. 24th 2018, Week 26th. Sunday
    June. 23rd 2018, Week 25th. Saturday
    June. 22 2018, Week 25th. Friday
    June. 21 2018, Week 25th. Thursday
    June. 20 2018, Week 25th. Wednesday
    【2018.10.11 C与C++基础】C Preprocessor的功能及缺陷(草稿)
    June.19 2018, Week 25th Tuesday
    June 18. 2018, Week 25th. Monday
  • 原文地址:https://www.cnblogs.com/Long-w/p/9798816.html
Copyright © 2020-2023  润新知