利用斐波那契数列的黄金分割原理对二分和插值查找的改进
二分,插值查找:https://blog.youkuaiyun.com/TinnCHEN/article/details/104437976
首先我们定义一个斐波那契数列
F = {0,1,1,2,3,5,8,13,21,34…}
int Fibonacci_Search(int *a,int n, int key){
int low, high, mid, i, k;
low = 1;
high = n;
k = 0;
while( n > F[k] - 1)
++k; //找到n在F中的位置
for(i = n; i < F[k] - 1; ++i)
a[i] = a[n]; //因为我们查找的数组中元素的个数不一定与斐波那契数列给定的个数相同,因此我们要把多余的空位按查找数组的最后一项补全
while(low < high){
/*
关于mid的理解很重要,我们知道斐波那契数列F[k] = F[k-1] + F[k-2]
k表示n在斐波那契数列中的位置
因此我们用F[k-1]来表示折半查找中"1/2"的位置。
符合黄金分割比,因此我们mid的选取即为low + F[k-1] - 1
*/
mid = low + F[k-1] - 1;
if(key < a[mid]){
high = mid - 1;
k = k - 1;
/*当key的值比mid处小时,high = mid -1好理解。
k = k - 1表示我们下一回合查找范围在low到F[k-1]之间,
即我们舍去了比F[k-1]到F[k]的元素。*/
}
else if(key > a[mid]){
low = mid + 1;
k = k - 2;
/*为什么k = k - 2?我们此时需要提高low的值。
原数组元素的个数为F[k] - 1,
因为我们知道mid是F[k-1]处的位置,
所以low到mid之间有F[k-1] - 1个元素。
mid到high之间有F[k-2] - 1个元素。
根据我们算法的思想,F[k-2] = F[k-3] + F[k-4],
所以我们要让k = k -2, low = mid + 1,
保证mid在下次循环中表示了在F[k-3]的位置*/
}
else{
if(mid <= n)
return mid;
else //mid > n说明mid在n的补全数值处,因此我们要返回n
return n;
}
}
return 0;
}