目录
在被查找数列中选取比较点(参考点)时,二分法采用的是中点,Fibonacci法采用的是黄金分割点。二分查找法是最直观的,Fibonacci查找法可能是最"美观",但都不是最科学的。那么如何选取最科学的那个比较点(参考点)呢?通常情况下被查找数列都不是等差的,也不知道数列的差值分布状态,没有办法确定到底选择哪个点作为"最优解"。插值算法则给出了一个大多数情况下的理论上最科学的比较点(参照点)。
插值查找多用于等差数列的查找。
四、插值查找
算法原理
mid=left+(key-iList[left])*(right-left)/(iList[right]-iList[left])
举例
第一次查找
以iList为被查找数列、key=7为例开始查找。
当前iList=range(0,10)=[0,1,2,3,4,5,6,7,8,9],是一个差值为1的等差数列,在插值查找给出的公式中的mid为参考点,left为被查找数列列首的下标,right为被查找数列列尾的下标,如下图所示:
从图中可以看到,第一次查找就找到了被查找数,在搜索等差数列时,插值查找是可能最快速的一种方法了。
代码实现
insertSort.py
from randomList import randomList
from quickSort import quickSort
import random
iList = quickSort(randomList(20))
def insertSearch(iList, key):
print("iList = %s" %str(iList))
print("Find The number : %d" %key)
iLen = len(iList)
left = 0
right = iLen -1
while right - left > 1:
mid = left + (key - iList[left]) * (right - left) // (iList[right] - iList[left])
if mid == left:
mid += 1 #当iList[right]和iList[left]相差太大时,有可能导致mid一直都等于left,从而陷入死循环
if key < iList[mid]:
right = mid
elif key > iList[mid]:
left = mid
else:
return mid
if key == iList[left]:
return left
elif key == iList[right]:
return right
else:
return -1
if __name__ == "__main__":
keys = [random.choice(iList), random.randrange(min(iList), max(iList))]
for key in keys:
res = insertSearch(iList, key)
if res >= 0:
print("%d is in the list, index is : %d\n" %(key, res))
else:
print("%d is not in the list\n" %key)
往期推荐:
排序篇:
查找篇:
如果喜欢这个系列的文章可以订阅我的算法设计与分析专栏,每天更新~