1. 斐波拉契查找算法
斐波拉契查找算法也称为黄金分割查找算法,它是在折半查找算法的基础上根据斐波拉契数列进行分割。折半法是取排序好的中间值进行分割,而斐波拉契查找算法是根据黄金分割点进行分割。
-
黄金分割点:黄金分割点是指把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比,其比值约等于0.618。
-
斐波拉契数列:又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)。斐波拉契数列越往后,前后两项的比值越接近0.618,也就是黄金比例的比值。
斐波拉契查找算法是在折半查找算法的基础上根据斐波拉契数列进行分割的。在斐波拉契数列中找到一个等于或略大于待查找长度的数F(n),待查找表长度扩展为F(n)-1(如果原来的数组长度不够F(n)-1,则需要扩展,扩展时候用原待查找表最后一项填充),mid = low + F(n)-1,已知 mid 为划分点(黄金分割点),将待查找表划分为左边、右边,即 F(n)个元素分割为前半部分F(n-1)-1个元素、后半部分F(n-2)-1个元素。
整体来说,它是根据斐波拉契数列的特点对有序表进行分割,寻找比例分割点mid,并进行比较,取舍范围。
2. 实现斐波拉契查找算法
def fibonacci_search(data, key):
# 需要一个现成的斐波那契列表。其最大元素的值必须超过查找表中元素个数的数值。
F = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,233, 377, 610, 987, 1597, 2584, 4181, 6765]
low = 0 # 低位
high = len(data) - 1 # 高位
# 为了使得查找表满足斐波那契特性,在表的最后添加几个同样的值
# 这个值是原查找表的最后那个元素的值
# 添加的个数由F[k]-1-high决定
k = 0
while high > F[k] - 1:
k += 1
i = high # 将i定位到high的位置
while F[k] - 1 > i: # 添加数据
data.append(data[high]) # 追加到high之后的位置上
i += 1
print("添加后的数据",data)
# 算法主逻辑,count用于展示循环的次数。
while low <= high: # 满足低位小于等于高位
# 为了防止F列表下标溢出,设置if和else
if k < 2:
mid = low
else:
mid = low + F[k - 1] - 1
print("低位位置:%s, 中间位置:%s,高位位置:%s" % (low, mid, high)) # 输出每次分割情况
if key < data[mid]: # 目标数据小于中间值数据,在左侧寻找
high = mid - 1 # 高位位置移到mid-1的位置
k -= 1 # 下标k此时减1
elif key > data[mid]: # 目标数据大于中间值数据,在右侧寻找
low = mid + 1 # 低位位置移到mid+1的位置
k -= 2 # 下标k此时减2
else: # 否则
if mid <= high: # 中间值小于等于mid
return mid # 此时的结果是mid就是目标值得位置,返回mid即可
else: # 如果mid大于了高位位置值
return high # 此时的结果直接返回high的值
return False
# 验证数据
data = [9,10,13,15,22,29,37,48,53] # 数据列表
key=int(input("请输入想要查找的数据:"))
result = fibonacci_search(data, key) # 调用斐波那契查找函数
print("目标数据",key,"的位置是", result) # 输出结果