数据结构与算法--排序与查找:斐波那契(黄金分割法)查找 Python实现斐波那契查找算法

阅读目录

思路

  • 基本介绍
    在这里插入图片描述
    在这里插入图片描述
  • 对 mid= low +F(k-1)-1的解释:
    在这里插入图片描述

Python实现

import copy


def get_fibonacci(max_size):  # 构建一个斐波那契数列
    fib = [0] * max_size
    fib[0] = 1
    fib[1] = 1
    for i in range(2, max_size):
        fib[i] = fib[i - 1] + fib[i - 2]
    return fib


def fibonacci_search(array, key):
    '''
    :param array: 传入的数组
    :param key:需要查找的关键码(值)
    :return:返回对应的下标,如果没有就返回-1
    '''
    low = 0
    high = len(array) - 1
    k = 0  # 表示斐波那契分割数值的下标
    mid = 0
    fib = get_fibonacci(max_size)  # 获取到菲波那切数列
    # 这一块是,只要数组长度大于斐波那契数列的值,就让值下标一直向后移动
    while high > fib[k] - 1:  # 获取到菲波那切数列 值 的下标
        k += 1
        
    # 因为fib[k] 的值可能大于 array 长度,因此我们需要使用扩充数组
    # Java 可以使用Arrays类,构造一个新数组,并指向 array[],属于浅拷贝
    # Java做法:int[] temp= Arrays.copyOf(a,f[k]); 不足部分会使用0填充,
    # 使用这种方法复制数组时,默认从源数组的第一个元素(索引值为 0)开始复制,
    # 目标数组的长度将为 length。如果 length 大于 srcArray.length,则目标数组中采用默认值填充;
    # 如果 length 小于 srcArray.length,则复制到第 length 个元素(索引值为 length-1)即止。
    # 这种做法,等于可以在原来的基础上扩展原数组,并预留一些空间

    # Python的做法:可以用用切片来确定不够的位置,然后填充
    temp_list = [0] * len(fib) # 构建一个和fib数列一样长度的数组
    temp_list[:len(array)] = copy.copy(array)  # 浅拷贝,拷贝数组所有值
    # fib 大于 array的部分,依次用array最后一个数填充
    for i in range(len(array), len(fib)):
        temp_list[i] = array[-1]
        
    while low <= high: # 使用while来循环处理,不用递归,找到需要找的数key
        mid = low + fib[k - 1] - 1
        if key < temp_list[mid]:  # 应该继续向数组的前面查找(左边)
            high = mid - 1
            # 全部元素 = 前面的元素 + 后边的元素
            # f[k] = f[k-1] + f[k-2]
            # 因为前面有f[k-1]元素,所以可以继续拆分f[k-1] = f[k-2] + f[k-3]
            k -= 1
        elif temp_list[mid] < key :  # 应该继续向数组的后面查找(右边)
            low = mid + 1
            # 全部元素=前面的元素+后边的元素
            # f[k] = f[k-1] + f[k-2]
            # 因为后面有f[k-2] 所以可以继续拆分f[k-1] = f[k-3] + f[k-4]
            # 即在f[k-2]的前面进行查找k-=2
            # 即下次循环mid=f[k-1-2]-1
            k -= 2
        else:  # 找到了,需要确定返回时,哪个是下标
            if mid <= high:
                return mid
            else:
                return high
    return -1


if __name__ == '__main__':
    li = [1, 8, 10, 89, 1000, 1234]
    max_size = 20
    get_fibonacci(max_size)
    print(fibonacci_search(li, 1000)) # 4
  • 总结:变化的确定mid_index的值时,用的是斐波那契数列数值的索引来确定的,整体思想还是二分法的思想,然后 最后操作的数组是浅拷贝的那份数组

也可以不用复制数组

fib = lambda n: n if n < 2 else fib(n - 1) + fib(n - 2)


def fib_search(arr, val):
    if len(arr) == 0:
        return 'arr is None'

    left = 0
    right = len(arr) - 1

    # 计算fib的值,这个值是大于等于arr的长度的,所以使用时要对key-1
    key = 0
    while fib(key) < len(arr):
        key += 1

    while left <= right:
        # 当x在分隔的后半部分时,fib计算的mid值可能大于arr长度
        # 因为mid是索引位置,这里要取arr长度-1
        mid = min(left + fib(key - 1) - 1, len(arr) - 1)
        if val < arr[mid]:
            right = mid - 1
            key -= 1
        elif val > arr[mid]:
            left = mid + 1
            key -= 2
        else:
            return mid
    return -1


def test_fib_search():
    arr = [1, 8, 10, 89, 1000, 1234]
    print(fib_search(arr, 1000)) # 4


if __name__ == '__main__':
    test_fib_search()
发布了146 篇原创文章 · 获赞 37 · 访问量 7863

猜你喜欢

转载自blog.csdn.net/storyfull/article/details/103657582
今日推荐