刚接触程序设计的人可能会看的斐波那契数列。其递推通项公式为
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; }
以下是运行结果截图
以上部分内容取自先取博客,在此表示感谢!