【查找】斐波那契查找

斐波那契查找:如果从文件中读取的数据记录的关键字是有序排列的(递增的或是递减的),则可以用一种比折半查找法更有效率的查找方法来查找文件中的记录,即为斐波那契查找,也称为黄金分割查找法
斐波那契查找的基本思想:斐波那契查找法与折半查找的基本思想类似,都是减少查找序列的长度,分而治之地进行关键字的查找。他的查找过程是:先确定待查找记录的所在的范围,然后逐渐缩小查找的范围,直至找到该记录为止(也可能查找失败)
在这里插入图片描述
作为折半查找法的加强优化版,它很好地将黄金分割的思想融入到关键字的查找中,它是根据斐波那契序列的特点对有序表进行分割的。它要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;
开始将k值与第F(k-1)位置的记录进行比较(即mid=low+F(k-1)-1),比较结果也分为三种
(1)key=k[mid],mid位置的元素即为所求;
(2)key>k[mid],low=mid+1,k-=2;
说明low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找
(3)key<k[mid],high=mid-1,k-=1。
说明low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1个,所以可以递归 的应用斐波那契查找
斐波那契搜索也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样的,斐波那契查找也属于一种有序查找算法
首先产生斐波那契数列:

void Fibonacci(int *f) //创建斐波那契数列 
{
 	int i;
 	f[0]=1;
 	f[1]=1;
 	for(i=2;i<N;++i)
  		f[i]=f[i-1]+f[i-2];
}

斐波那契查找:

int search(int *a,int key,int n)
{
 	int i,low=0,high=n-1;
 	int mid=0,k=0,F[N]; 
 	Fibonacci(F);
 	while(n>F[k]-1)//计算出n在斐波那契中的数列 
  		++k;
 	for(i=n;i<F[k]-1;++i)//补全数组
  		a[i]=a[high];
 	while(low<=high)
 	{
  		mid=low+F[k-1]-1;//根据斐波那契数列进行分割
  		if(a[mid]>key)
  		{
   			high=mid-1;
   			k-=1;
  		}
  		else if(a[mid]<key)
  		{
   			low=mid+1;
   			k-=2;
  		}
  		else
  		{
   			if(mid<=high)//如果为真则找到相应位置 
    				return mid;
   			else
    				return -1;
  		} 
 	} 
}

【实例】
有一个数组A[10],里面存放了10个整数,顺序递增。任意输入一个数字n,找到n在数组中的位置。如果n不属于该数组A,显示错误提示。
        A[10]={2,3,5,7,9,11,12,15,19,22}
【分析】

#include<stdio.h>
#define N 20 
void Fibonacci(int *f) //创建斐波那契数列 
{
 	int i;
 	f[0]=1;
 	f[1]=1;
 	for(i=2;i<N;++i)
  		f[i]=f[i-1]+f[i-2];
}
int search(int *a,int key,int n)
{
 	int i,low=0,high=n-1;
 	int mid=0,k=0,F[N]; 
 	Fibonacci(F);
 	while(n>F[k]-1)//计算出n在斐波那契中的数列 
  		++k;
 	for(i=n;i<F[k]-1;++i)//补全数组
  		a[i]=a[high];
 	while(low<=high)
 	{
  		mid=low+F[k-1]-1;//根据斐波那契数列进行分割
  		if(a[mid]>key)
  		{
   			high=mid-1;
   			k-=1;
  		}
  		else if(a[mid]<key)
  		{
   			low=mid+1;
   			k-=2;
  		}
  		else
  		{
   			if(mid<=high)//如果为真则找到相应位置 
    				return mid;
   			else
    				return -1;
  		} 
 	} 
}
int main()
{
 	int a[N]={2,3,5,7,9,11,12,15,19,22};
 	int k,r=0;
 	printf("请输入要查找的数字:");
 	scanf("%d",&k);
 	r=search(a,k,10);
 	if(r!=-1)
  		printf("\n在数组的第%d个位置找到元素:%d\n",r+1,k);
 	else
  		printf("\n未在数组中找到该元素:%d\n",k);
 	return 0;
}

运行结果为:
在这里插入图片描述
注意:数组的下标从0开始,故要在原返回值上+1,才为元素的位置。

猜你喜欢

转载自blog.csdn.net/weixin_44321600/article/details/86671733