运用插值法解决静态查找问题

来源:互联网 发布:中国水平知乎 编辑:程序博客网 时间:2024/04/28 14:44

静态查找问题描述为:给定一个整数和一个数组,查找该整数在这个数组中的位置或返回一个不存在的标志,在查找过程中数组中的数据是不变的。例如在一个电话号码本里查找某一个人。如果数组中的数据是无序的,我们只能用顺序查找来检查数组中的每一个值,直到找到一个匹配的为止。如果数组中的数据已经排过序,就可以使用二分搜索来代替顺序查找。二分搜索每次都是从给定查找范围的中间开始而不是从端点开始,这样可以提高查找效率。二分搜索在查找一个有序的静态数组时很快,是我们经常使用的方法。但是如果我们要查找的值在靠近端点的位置,这时再使用二分搜索显然是不明智的。这时就可以使用更快的一种查找方法插值法。插值法不是简单地使用中间值来查找,而是要对查找值所在的位置做一个正确的猜测,来确定要查找的一下项。

下面是插值法的boo实现:

Boo代码  收藏代码
  1. import System  
  2.   
  3. def interpolationSearch(obj as int, *args as (int)):  
  4.     low = 0  
  5.     high = args.Length - 1  
  6.     next as int  
  7.     while low < high:  
  8.       //to determine the position of the next item  
  9.         next = low + ((obj - args[low]) / (args[high] - args[low])) * (high - low - 1)  
  10.         if args[next] < obj:  
  11.             low = next + 1  
  12.         else:  
  13.             high = next  
  14.           
  15.     if args[low] == obj:  
  16.         return low  
  17.       
  18.     return -1  

 

Boo代码  收藏代码
  1. >>>a = array(range(31000))  
  2. ...  
  3. >>>interpolationSearch(85, *a)  
  4. 82  
  5. >>>  

 上面在数组a中查找85所在的位置,返回82.





插值搜索

     这是一种和二分比较相似的查找的算法, 不过不同的是, 对于分布比较均匀的较大的数组, 插值查找有时能够一次就搜索到位.. 
  为什么能够这么快呢`? 看网上没有什么关于这种算法的描述, 我就来描述一下吧. 
  首先要知道一点, 这种搜索方式只能够针对顺序表进行,, 再一个要理解顺序表中的一个特点, 在顺序表中查找是否存在一个值, 此时我可以对顺序表中的任意一个元素进行比较, 如果我要在A中寻找值为t的元素是否存在, 那么我用a[i]和t进行比较, (a[i]可以是顺序表中任意一个元素..), 如果a[i]==t的话, i就是t所在的位置, 如果a[i] > t,  那么说明t一定不在在a[i], a[i+1]....a[n-1], a[n]... 也就是说现在只需要对a[1]..a[i-1]进行搜索即可.. 
  好好理解一下吧, 如果上面的理解不了, 那么插值查找就不好理解.. 
  接下来我用low和high来保存该搜索的范围, 在刚开始low=0, hight=n-1. 设i是在low到high之间的相对位置.. 如: 若 i= 0, low = 0, 那么就该让t和a[i + low]比较, 即判断t是否和a[0]相等.. 
  现在就是要确定i在哪里了.. 
  假设顺序表的分布比较均匀, 那么有下面的方程: 
  (t - a[low]) : (i - low) = (a[high] - a[low]) : (high - low) 
  i = (t - a[low]) * (high - low) / (a[high] - a[low]) + low; 
  差不多了吧... 
  我的语言表达能力有限, 若还不大理解, 就看代码吧:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* a是待搜索的顺序表,, size是a的长度, t 是待搜索的值 */ 
int search(int a[], int size, int t) 
    int low = 0, high = size - 1
    int pos; 
    while(low <= high){ 
        pos = (t - a[low])/(a[high] - a[low])*(high - low) + low; 
        if(a[pos] == t){ 
            return pos; 
        
        if(a[pos] > t){ 
            high = pos - 1
        }else
            low = pos + 1
        
    
    return -1
}