原创作品,出自 “晓风残月xj” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。
由于各种原因,可能存在诸多不足,欢迎斧正!
刚接触程序设计的人可能会看的斐波那契数列。其递推通项公式为
fib[i]=1 i=0,1
fib[i]=fib[i-1]+fib[i-2]; i>2
这样一个可以根据数学推到进一步求得与i相关的通项公式
我们知道0.618是个魔力数,即通常所说的黄金分割点。黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。
1.设data[i]为有序数列,i=0,1…n-1;计算斐波那契数列前m项,m是保证fib[m]>=n的最小数。
2.low=0,high=n-1;
3.mid=low+fib[m-1]-1
如果data[mid]>key,则说明可能在左半部分,m=m-1;
如果data[mid]<key,则说明可能在右半部分,m=m-2;
则否找到key,正确定位即可。
该算法的时间复杂度为O(n*Log(n)),和二分查找一样,但可以避开除法运算,在计算机中除法运算的占用资源比加减高得多。当然在很多时候可以用位运算避开除2运算。
#include<iostream>
using namespace std;
const int MAXN=20;
int fib[MAXN];
//预处理求出Fibonacci数列
void GetFibonacci()
{
fib[0]=1,fib[1]=1;
for(int i=2;i<MAXN;i++)
fib[i]=fib[i-2]+fib[i-1];
}
//斐波那契数列查找
int FibonacciSearch(int key,int data[],int n,int &count)
{
int m=0;
while(n>fib[m]-1)
m++;
for(int i=n;i<=fib[m]-1;i++)
data[i]=data[n-1];
int low=0,high=n-1,mid;
while(low<=high)
{
count++;
mid=low+fib[m-1]-1;
if(data[mid]>key)
{
high=mid-1;
m=m-1;
}
else if(data[mid]<key)
{
low=mid+1;
m=m-2;
}
else //找到这样的key
{
if(mid<n)
return mid;
return n-1;//原数组组后一个数
}
}
return -1;
}
//二分查找
int BinarySearch(int key,int data[],int n,int &count)
{
int low=0,high=n-1,mid;
while(low<=high)
{
count++;
mid=(low+high)/2;
if(data[mid]>key)
{
high=mid-1;
}
else if(data[mid]<key)
{
low=mid+1;
}
else return mid;
}
return -1;
}
int main()
{
int data[100]={1,3,5,7,9,12,23,54,65,78,80,100};
GetFibonacci();
double Ave=0;
int count;
printf("以下是斐波那契数列查找的结果:\n");
for(int i=0;i<12;i++)
{
count=0;
int ans=FibonacciSearch(data[i],data,12,count);
Ave+=ans;
printf("%d出现在第%d位置,查找了%d次\n",data[i],ans,count);
}
printf("斐波那契数列平均查找参数为%0.2lf\n",Ave/12);
Ave=0;
printf("以下是二分查找的结果:\n");
for(i=0;i<12;i++)
{
int ans=BinarySearch(data[i],data,12,count);
Ave+=ans;
printf("%d出现在第%d位置,查找了%d次\n",data[i],ans,count);
}
printf("二分查找平均查找参数为%0.2lf\n",Ave/12);
return 0;
}
以下是运行结果截图
以上部分内容取自先取博客,在此表示感谢!