欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

斐波那契查找(黄金分割法查找)

程序员文章站 2022-04-08 09:13:21
...

要想能够理解这一算法,需要先了解
1.二分查找
https://blog.csdn.net/qq_35423154/article/details/101383518
2.斐波那契数
https://blog.csdn.net/qq_35423154/article/details/101684466

黄金分割具有严格的比例性、艺术性、和谐性,蕴藏着丰富的美学价值,这一比值能够引起人们的美感,被认为是建筑和艺术中最理想的比例。
斐波那契查找(黄金分割法查找)
斐波那契查找(黄金分割法查找)
蒙娜丽莎,断臂的维纳斯,这些我们经常见到的艺术品就是采用了黄金分割法,即0.618的比例。

而我们所熟知的斐波那契数列又叫做黄金分割数列,当它无限往下增加时,越到后面两个数的比例就越来越接近0.618即黄金分割点。
在我们眼里,编程也是一种艺术,那么我们能否利用这个万能的黄金分割法,运用到查找中呢?答案是肯定的,我们将斐波那契数与二分查找相结合,就得到了斐波那契查找,它与二分查找的思路相同,但是借助斐波那契数,可以仅仅使用加减法来完成查找,大大提高了效率。

那我们该如何实现呢?
例如我们要在

	int a[] ={1,3,5,7,9,11,13,15,17,19};

查找这个17
首先我们需要找到这个数组的长度n在斐波那契数中的位置
斐波那契查找(黄金分割法查找)
它所处的位置是斐波那契数列中的第七位,而a中只有10个元素,而斐波那契的第七个数为13,所以我们需要补全数组,将数组补充至13-1位,补充的值为最后一项的值
斐波那契查找(黄金分割法查找)
斐波那契查找(黄金分割法查找)
如果我们的key值小于mid的时候,我们按照上图,结合二分查找的思想,我们取到左边的一块,斐波那契数下标减1,我们的high值变为mid-1
而如果当key值大于mid的时候我们取到右边的一块,斐波那契数下标减2,我们的low值变为mid + 1

当我们的mid<=n时,说明mid即为我们查找到的下标。
当mid>n时,说明这个时候我们的mid为补全的下标,我们只需要返回一个原数组的最大下标就可以
斐波那契查找(黄金分割法查找)

完整代码:

#include<stdio.h>
#define MAXSIZE 100
void GitFib(int* fib)
{
	int i;
	fib[0] = 0;
	fib[1] = 1;
	for(i = 2; i < MAXSIZE; i++)
	{
		fib[i] = fib[i - 1] + fib[i - 2];
	}
} 
int FibonacciSearch(int *a,int n,int key)
{
	int i,mid,low=0,high= n ,k=0;
	int fib[MAXSIZE] = {0};
	GitFib(fib); 
	while (n > fib[k] - 1)
	{
		k++;
	}
	//找出n在斐波那契数中的位置 
	for (i = n; i<fib[k] -1; i++)
	{
		a[i] = a[n];
	}
	//补全数组 
	while (low <= high)
	{
		mid = low + fib[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;
			else
				return n; 
		}
	}
}
int main()
{
	int a[] ={1,3,5,7,9,11,13,15,17,19};
	int key,i,n;
	n = sizeof(a)/sizeof(a[0])-1;
	printf("请输入要查找的数据:");
	scanf("%d",&key);
	printf("%d\n",FibonacciSearch(a,n,key));
	
	return 0;
}

插值查找,斐波那契查找都是二分查找的一种变式,它们的本质上的不同时分隔点的选择不同,实际使用的时候根据数据的综合特点考虑再进行选择

相关标签: 斐波那契查找