查找算法——斐波那契查找

1、算法介绍

 斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….,随着数列递增,前后两个数的比值趋近于0.618的黄金分割比。

斐波那契查找便是将黄金比例运用于查找中。

(1)查找序列arr元素个数:n

(2)斐波那契数:F(1)=1,F(2)=1, F(k)=F(k-1)+F(k-2)(k>=3,k∈N*);

(3)构建新的查找序列arrNew元素个数:m = F(k)-1,需满足 m 大于等于 n,即F(k)-1>=n

(4)取F(k)-1的原因:F(k)-1= F(k-1)-1 + F(k-2)-1 + 一个查找数

如 F(7)-1 = 13-1 = F(6)-1 + F(5)-1 + 1 = 8-1 + 5-1 + 1

(5)新的查找序列arrNew前面数据与arr相同,后面多余位的值全部等于arr[n-1]

(6)查找规则类似二分查找

2、代码实现

 2.1、golang

package main

import (
	"fmt"
)

func main() {
	fib := CreateFibnacci(20)
	fmt.Println(fib)
	slice := []int{1, 2, 3, 4, 5, 6} //升序序列
	key := 100
	index := SearchFibnacci(slice, key)
	if index == -1 {
		fmt.Printf("%v不存在元素%v\n", slice, key)
	} else {
		fmt.Printf("%v位于%v下标为%v的位置。\n", key, slice, index)
	}
}

//构建斐波那契数列
func CreateFibnacci(n int) []int {
	res := []int{1, 1}
	for i := 2; i < n; i++ {
		res = append(res, res[i-1]+res[i-2])
	}
	return res
}

//斐波那契查找
func SearchFibnacci(slice []int, key int) int {
	n := len(slice)
	fib := CreateFibnacci(20)
	//1、斐波那契下标,需满足F(k)-1>=n
	k := 0
	for !(fib[k]-1 >= n) {
		k++
	}
	//2、构建新序列,多出位补slice[n-1]
	tempS := make([]int, fib[k]-1)
	copy(tempS, slice)
	for i := n; i < len(tempS); i++ {
		tempS[i] = slice[n-1]
	}
	//3、开始斐波那契查找
	left, right := 0, n-1
	for left <= right {
		mid := left + fib[k-1] - 1
		if tempS[mid] > key {
			right = mid - 1
			k -= 1 //查找值在前面的F(k-1)位中
		} else if tempS[mid] < key {
			left = mid + 1
			k -= 2 //查找值在后面的F(k-2)位中
		} else {
			if mid < n {
				return mid
			} else { //位于tempS的填补位
				return n - 1
			}
		}
	}
	return -1
}

2.2、python3

# 4、斐波那契查找
def create_fibonacci(n):
    arr = [1, 1]
    for i in range(2, n, 1):
        arr.append(arr[i - 1] + arr[i - 2])
    return arr


# 斐波那契查找
def serarch_fibonacci(arr, key):
    n = len(arr)
    # 创建斐波那契数组
    fib_arr = create_fibonacci(20)
    print(fib_arr)
    # 获取斐波那契下标,需满足F(k)-1>=n
    k = 0
    while not (fib_arr[k] - 1 >= n):
        k += 1
    # 构建新序列,多出位补arr[n-1]
    tempArr = arr.copy()
    for i in range(n, fib_arr[k] - 1, 1):
        tempArr.append(arr[n - 1])
    print(tempArr)
    # 开始查找
    left, right = 0, n - 1
    while (left <= right):
        mid = left + fib_arr[k - 1] - 1
        if (tempArr[mid] > key):
            right = mid - 1
            k -= 1
        elif (tempArr[mid] < key):
            left = mid + 1
            k -= 2
        else:
            if (mid < n):
                return mid
            else:
                return n - 1
    return -1


if __name__ == '__main__':
    arr = [1, 2, 3, 4, 5, 6, 7, 8]
    key = 7
    index = serarch_fibonacci(arr, key)
    if index == -1:
        print("%s不存在元素%s。" % (arr, key))
    else:
        print("%s位于%s下标为%s的位置。" % (key, arr, index))

  

posted @ 2019-05-30 14:34  笃志弘毅  阅读(1047)  评论(0编辑  收藏  举报