插值查找【转】

10.1.2.3    插值查找(Interpolation Search )

先来看一个实际问题

我们在一本英汉字典中寻找单词“worst”,我们决不会仿照对半查找(或Fibonacci查找)那样,先查找字典中间的元素,然后查找字典四分之三处的元素等等. 事实上,我们是在所期望的地址(在字典的很靠后的地方)附近开始查找的,我们称这样的查找为插值查找.

可见,插值查找不同于前面讨论的几种查找算法,前面介绍的查找算法是基于严格比较的,即假定我们对线性表中元素的分布一无所知(或称没有启发式信息). 然而实际中,很多查找问题所涉及的表满足某些统计的特点.

 

 

插值查找在实际使用时,一般要满两个假设条件

(1)      每一次对数据的访问与通常的指令相比,费用都是相当昂贵的。例如,待查找的表一定是在磁盘而非内存中,因而每一次比较都要进行磁盘访问。

(2)    数据不仅是已被排好序的,而且呈现均匀分布特征

   例如,一个电话本中的数据就是非常好的均匀分布。如果输入数据为{1,2,4,8,16,…},那么这个分布就不是均匀的。

   为了简便,我们假定表中记录的关键字是数字类型,且K1<K2<…<Kn在(K0,Kn+1)区间上呈均匀分布.

   设变元K给定,且K0<K<Kn+1 ,则由均匀分布的假定,我们可用线性插值来决定K的期望地址n(K-K0)/(Kn+1-K0.    //k为键值,ko为第零个元素的值

   插值查找算法的实现是这样的:

    如果知道Ks<K<Ke,则我们将在处进行测试,而接下来的过程类似于对半查找算法

     算法Interpolation (Rn. found) 

          // 插值查找算法。表R1,R2,…,Rn相应的关键词 K1<K2<…<Kn ,且在区间(K0,Kn+1)上呈均匀分布

  Ip1  [初始化]

       s←0 .e←n+1 .found←false .                  //s是start的意思,e是end的意思   found初始化为false,表示未找到

  Ip2 

         WHILE e-s>1 AND NOT(found)DO {

             m← s+{(K-Ks)/(Ke - Ks)}*(e-1 - s)+0.5          //k为键值,ks为第s个元素的值,ke为第e个元素。加0.5是为了向上取整               

       IF K<Km  THEN  e←m .

       IF K>Km  THEN  s←m .

                IF K = Km  THEN found←true)

   }

代码如下:

View Code
1 #include <stdio.h>
2 int sqlList[20] = {5, 9, 13, 17, 22, 31, 47, 68, 71};
3
4 int biSearch(int sqlList[], int num, int element) {
5 int from = 0;
6 int to = num-1;
7
8 while(from <= to) {
9 int mid = (from + to) >> 1;
10 if(sqlList[mid] == element)
11 return mid;
12 if(sqlList[mid] > element)
13 to = mid - 1;
14 else
15 from = mid + 1;
16 }
17 return -1;
18 }
19
20 int insertValueSearch(int sqlList[], int num, int element) { //插值查找代码
21   int from = 0;
22 int to = num-1;
23
24 while(from <= to) {
25 int mid = (int)(from + (element - sqlList[from]) //int为强制转换为整型
26 /(sqlList[to] - sqlList[from]) * (to - from) + 0.5); //+0.5为向上取证
27 if(sqlList[mid] == element)
28 return mid;
29 if(sqlList[mid] > element)
30 to = mid - 1;
31 else
32 from = mid + 1;
33 }
34 return -1;
35 }
36
37
38 void insert(int sqlList[], int num, int element) {
39 int from = 0;
40 int to = num-1;
41 while(from <= to) {
42 int mid = (from + to) >> 1;
43 if(sqlList[mid] > element)
44 to = mid-1;
45 else
46 from = mid+1;
47 }
48
49 for(to = num; to > from; to--) //插入位置后面的元素们往后一位
50 sqlList[to] = sqlList[to-1];
51 sqlList[from] = element;
52 }
53
54 int main() {
55 printf("\n\n\t\t%d\n", biSearch(sqlList, 9, 22));
56 printf("\n\n\t\t%d\n", insertValueSearch(sqlList, 9, 22));
57 insert(sqlList, 9, 15);
58 printf("\n\n\t\t%d\n", biSearch(sqlList, 10, 15));
59 }
posted @ 2011-03-12 11:33  jnje  阅读(789)  评论(0编辑  收藏  举报