斐波那契查找
在介绍斐波那契查找之前我们要先了解两件事,黄金分割和斐波那契数列,二者是啥关系。
首先是黄金分割(也叫黄金比例),这个词经常出现在一些建筑物的设计,黄金分割的近似值是0.618。斐波那契数列又称黄金比例数列,指的是这样的数列:1、1、2、3、5、8、13、21、34……,这个数列从第三项开始,每一项都等于前两项之和(F[K] = F[K-1] + F[K-2]);随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以把黄金比例运用到查找当中。
斐波那契查找依旧基于数组是有序数组,并使数组长度与斐波那契数组元素相匹配,之后类似于二分查找。
斐波那契查找总共分为以下几步:
1.构建斐波那契数列
2.计算数组长度对应的斐波那契数列元素个数
3.对数组进行填充
4.循环进行区间分割,查找中间值
5.判断中间值和目标值的关系,确定更新策略
斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1).
算法思路:
-
相等,mid位置的元素即为所求
-
大于,low=mid+1,k-=2;
-
小于,high=mid-1,k-=1。
说明:
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个,所以可以递归的应用斐波那契查找。
代码:
#include "stdafx.h"
#include <memory>
#include <iostream>
using namespace std;
const int max_size=20;//斐波那契数组的长度
/*构造一个斐波那契数组*/
void Fibonacci(int * F)
{
F[0]=0;
F[1]=1;
for(int i=2;i<max_size;++i)
F[i]=F[i-1]+F[i-2];
}
/*定义斐波那契查找法*/
int FibonacciSearch(int *a, int n, int key) //a为要查找的数组,n为要查找的数组长度,key为要查找的关键字
{
int low=0;
int high=n-1;
int F[max_size];
Fibonacci(F);//构造一个斐波那契数组F
int k=0;
while(n>F[k]-1)//计算n位于斐波那契数列的位置
++k;
int * temp;//将数组a扩展到F[k]-1的长度
temp=new int [F[k]-1];
memcpy(temp,a,n*sizeof(int));
for(int i=n;i<F[k]-1;++i)
temp[i]=a[n-1];
while(low<=high)
{
int mid=low+F[k-1]-1;
if(key<temp[mid])
{
high=mid-1;
k-=1;
}
else if(key>temp[mid])
{
low=mid+1;
k-=2;
}
else
{
if(mid<n)
return mid; //若相等则说明mid即为查找到的位置
else
return n-1; //若mid>=n则说明是扩展的数值,返回n-1
}
}
delete [] temp;
return 0;
}
int main()
{
int a[] = {0,1,4,35,47,53,62,78,88,99};
int key=47;
int index=FibonacciSearch(a,sizeof(a)/sizeof(int),key);
if(index == 0)
{
cout<<"没有找到"<<key;
}
else
{
cout<<key<<" 的位置是:"<<index;
}
return 0;
}