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))
