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 ", slice, key) } else { fmt.Printf("%v位于%v下标为%v的位置。 ", 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))