博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
查找算法之插值查找
阅读量:4501 次
发布时间:2019-06-08

本文共 3038 字,大约阅读时间需要 10 分钟。

参考

1.

 

主要思想

二分查找算法是傻瓜式的将待查找序列一分为二进行查找,直到找到或者查找失败。插值查找算法,是针对待查找序列均匀分布特点、结合二分查找算法进行改进的一种自适应查找算法。

一般的,二分查找范围一个很重要的点

middle = (left + right)/2

而插值查找,可根据目标元素在待查找序列中的到边界值的大小来估算到边界的距离,通过估算的距离快速缩小目标所在序列的范围,即

middle = left + (target - a[left]) / (a[right] - a[left]) * (right - left), 当然有前提条件left < right, 不能取等号。

 

先决条件

与二分查找算法先决条件一样,可以理解为二分查找算法的优化

1. 待查存储在顺序表中(数组,而非链表);

2. 待查顺序表有序(递增,递减都可以,相邻元素相等也可以)

 

例程

 递增序列a = [3, 6, 9, 12, 20, 25, 30 ,36],

1. 待查找目标t=25 ,正常结果是返回5

2. 待查找目标t=11,正常结果是查找失败(返回-1)

 

 

 

网上流行的代码:乍一看是没什么问题,实际上,初始情况或者中间计算过程可能存在mid < left或者mid>right的情况。这显然不合理,因为没有在left~right正常范围进行查找。

#error realizationdef interpolation_search(a, target):    left = 0    right = len(a) - 1    print 'left = %d, right = %d'%(left, right)    while left < right:        middle = left + (target - a[left]) * (right - left) / (a[right] - a[left])        print 'left=%d, middle=%d, right=%d'%(left, middle, right)        if a[middle] < target:            left = middle + 1        elif a[middle] > target:            right = middle - 1        else:            print 'sucess to find out the target'            return middle    if left == right:        middle = left        if a[middle]  == target:            print 'sucess to find out the target'            return middle    print 'fail to find out the target'    return -1data = [3, 6, 9, 12, 20, 25, 30,36]print interpolation_search(data, 25)print interpolation_search(data, 11) #result in endless loop

 

 如何解决middle超界限的问题?

假设第n步,出现middle(n) < left(n),也就意味着a[middle(n)] < a[left(n)](因为a是递增序列);

那么在前一步,a[middle(n-1)] > a[left(n-1)] , 导致left_n=middle(n-1) + 1 > middle(n-1),

进而重复到middle(n) = left(n) + (target - a[left(n)]) / (a[right(n)] - a[left(n)]) * (right(n) - left(n)) < left(n);

 

 不妨在第n步,添加对middle(n), left(n)的判断,如果发现middle(n) < left(n)及时终止循环,返回查找失败状态。

#modified realizationdef interpolation_search(a, target):    left = 0    right = len(a) - 1    print 'left = %d, right = %d'%(left, right)    while left < right:        middle = left + (target - a[left]) * (right - left) / (a[right] - a[left])        print 'left=%d, middle=%d, right=%d'%(left, middle, right)        if middle >= left and middle <= right:            if a[middle] < target:                left = middle + 1            elif a[middle] > target:                right = middle - 1            else:                print 'sucess to find out the target'                return middle        else:            print 'fail to find out the target'            return -1    if left == right:        middle = left        if a[middle]  == target:            print 'sucess to find out the target'            return middle    print 'fail to find out the target'    return -1data = [3, 6, 9, 12, 20, 25, 30,36]print interpolation_search(data, 25)print interpolation_search(data, 11)

 

运行结果:

left = 0, right = 7left=0, middle=4, right=7left=5, middle=5, right=7sucess to find out the target5left = 0, right = 7left=0, middle=1, right=7left=2, middle=2, right=7left=3, middle=2, right=7fail to find out the target-1

 

转载于:https://www.cnblogs.com/fortunely/p/9625216.html

你可能感兴趣的文章
学习笔记之传说中的圣杯布局
查看>>
oh-my-zsh的使用
查看>>
共享内存的设计
查看>>
deque容器
查看>>
2017-2018-1 20155203 20155204 实验二 固件程序设计
查看>>
三方贸易-drop ship
查看>>
Android RenderScript 使用 Struct 及其下标的赋值
查看>>
【题解】BZOJ P1801 dp
查看>>
杂项-软件生命周期:软件生命周期
查看>>
小程序:小程序能力
查看>>
P1578 奶牛浴场 有障碍点的最大子矩形
查看>>
OpenCV学习:体验ImageWatch
查看>>
socket_循环接收消息
查看>>
I/O基础之概念
查看>>
各种算法的优缺点:
查看>>
poj 2513 Colored Sticks 字典树
查看>>
BZOJ 1266: [AHOI2006]上学路线route Floyd_最小割
查看>>
Softmax函数
查看>>
.NET 向SQL里写入非Text类型
查看>>
HAOI2006 受欢迎的牛
查看>>