裴波那契查找法(Fibonacci Search)

(由于本文参考多篇文章,无法注明转载出处, 因此没有标注转载,但在下方注明了所有参考过的网址,特此说明)

3.裴波那契查找法(Fibonacci Search)

3.1)斐波那契数列:

   斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

    如果设F(n)为该数列的第n项(n∈N*),那么这句话可以写成如下形式::F(n)=F(n-1)+F(n-2)

 

3.2)裴波那契查找(Fibonacci Search)是利用黄金分割原理实现的查找方法。

  斐波那契查找的核心是:

   1.当key == a[mid]时,查找成功;(但是计算中间位置mid的方法不同)

   2.当key < a[mid]时,新的查找范围是low至mid-1, 此时范围个数为F[k-1] - 1个,即数组左边的长度;

   3.当key < a[mid]时,新的查找范围是mid+1至high,此时范围个数为F[k-2] - 1个,即数组右边的长度;

   解释: 和二分法相似,但是二分法是每次都把数组均为分为二,用的是(mid=(low+high)/2),但是裴波那契查找,也是把数组一分为二,但是左右的长度分别为,左侧F[k-1] - 1个,右侧F[k-2] - 1个(参考原理就是上面提到的F(n)=F(n-1)+F(n-2)),因此计算mid的公式为(mid = low + F[k-1] - 1)。即:折半查找每次将查找表对半分,裴波那契查找就是将拆分方式换成裴波那契数列

下图为示意图

         裴波那契查找法(Fibonacci Search)

 

3.3)代码:

/*定义斐波那契查找法*/
int Fibonacci_Search(int *a, int n, int key)
{
	int low, high, mid, i, k;
	int F[MAXSIZE];
 
    Fibonacci(F); //构造一个斐波那契数组F
	low = 1;   //最低下标记录为首位
	high = n;  //最高下标记录为末位
	k = 0;
 
	while(n > F[k]-1)  //计算n位于斐波那契数列的位置
	{
		k++;
	}
 
	for(i=n; i<F[k]-1; i++)  //将a的元素扩展到(某斐波那契数 - 1),即F[k]-1
	{
		a[i] = a[n];
	}
 
	while(low <= high)
	{
		mid = low + F[k-1] - 1;   //计算当前分割的下标
		if(key < a[mid])
		{
			high = mid - 1;
			k -= 1;
		}
		else if(key > a[mid])
		{
			low = mid + 1;
			k -= 2;
		}
		else
		{
			if(mid <= n)
				return mid;   //若相当则说明mid即为查找到的位置
			else
				return n;     //若mid>n则说明是扩展的数值,返回n
		}
	}
	return -1;
}

说明:

      1.需要判断现在数组的个数和斐波那契数列的大小关系。如果少要进行扩充,比如斐波那契数列是1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...,但数组的大小是14个元素时,14介于数字13和21之间,也就是k=7和k=8之间,那么需要把数字空充到F【k】-1个,也就是扩充到20个,也需要添加6个元素,然后再来计算mid,才依次进行比较;

      2.注意比较完之后,两个k的计算不同,如果要对左侧继续进行比较,则需要k-=1;如果需要右侧,则k-=2

 

3.4)效率分析:

     关于斐波那契查找, 如果要查找的记录在右侧,则左侧的数据都不用再判断了,不断反复进行下去,对处于当众的大部分数据,其工作效率要高一些。所以尽管斐波那契查找的时间复杂度也为O(logn)但就平均性能来说,斐波那契查找要优于折半查找。可惜如果是最坏的情况,比如这里key=1,那么始终都处于左侧在查找,则查找效率低于折半查找。
 

还有关键一点,折半查找是进行加法与除法运算的(mid=(low+high)/2),插值查找则进行更复杂的四则运算(mid = low + (high - low) * ((key - a[low]) / (a[high] - a[low]))),而斐波那契查找只进行最简单的加减法运算(mid = low + F[k-1] - 1),在海量数据的查找过程中,这种细微的差别可能会影响最终的效率。
 

参考:https://www.cnblogs.com/praglody/p/6739989.html

https://blog.csdn.net/qq_16234613/article/details/52690150

https://baike.sogou.com/v267267.htm?fromTitle=斐波那契数列

https://blog.csdn.net/zpluw/article/details/7757331

上一篇:python基础教程(二)


下一篇:c – 这是斐波纳契系列生成的更好方法