900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 斐波那契查找(Fibonacci Search)和折半查找

斐波那契查找(Fibonacci Search)和折半查找

时间:2021-02-09 22:20:26

相关推荐

斐波那契查找(Fibonacci Search)和折半查找

两个查找算法都是针对有序数组进行查找,不同点在于分界点的取值不同。

算法介绍

折半查找很简单,每次与当前区间的中点进行比较,然后决定查找前一部分还是后一部分。

Fibonacci查找利用了Fibonacci序列每一项等于前两项和的特点进行划分,然后再在前一部分或者后一部分进行查找。

对于一个数组,我们首先将他填充成长度为F[k]-1的数组,其中F[]表示斐波那契数列。为什么非要填充成F[k]-1呢?

我们知道斐波那契数列有如下性质:

F[k]=F[k−1]+F[k−2]F[k]=F[k-1]+F[k-2] F[k]=F[k−1]+F[k−2]

朴素的想法是我们对区间[l,r)进行划分,其中r-l=F[k],分界点选择为mid=l+F[k-1](当然我们也可以选择F[k-2],这取决于数据集中在哪里)。当我们将需要查询的数据xa[mid]比较以后我们可能需要查询左边或者右边的区间,即[l,mid)或者[mid+1,r),而这个时候后面那个区间的长度为F[k-2]-1,不再是斐波那契数列。这显然不是我们想要看到的结果。

我们不妨尝试将区间的长度变成F[k]-1,将分界点设置为mid=l+F[k-1]-1,这时我们发现右边的区间的长度将变成F[k-2]-1,仍旧满足这种结构。这样我们就可以递归地进行处理。

我们也可以尝试将区间长度变为F[k]+1,只是这样的话我们就无法将区间长度变为0退出搜索。

实现代码

#include<cstdio>#include<algorithm>#include<cstdlib>using namespace std;int init(int* F,int n){F[0]=1;F[1]=1;int ret=2;while(1){F[ret]=F[ret-1]+F[ret-2];if(F[ret]-1>=n)break;++ret;}return ret;}int FiboSearch(int *a,int *F,int k,int l,int r,int x){if(r<l) return -1;int mid=l+F[k-1]-1;if(x==a[mid]) return mid;if(x<a[mid]){return FiboSearch(a,F,k-1,l,mid,x);}else{return FiboSearch(a,F,k-2,mid+1,r,x);}}int main(){int n,k;printf("n="); scanf("%d",&n);printf("k="); scanf("%d",&k);int F[64],len;int a[128];len=init(F,n);for(int i=0;i<n;++i){scanf("%d",&a[i]);}if(k>a[n-1] || k<a[0]){printf("-1\n");return 0;}printf("%d\n",FiboSearch(a,F,len,0,F[len]-1,k));return 0;}

性能分析

斐波那契查找算法同折半查找一样复杂度都是O(logn)的,不同点在于,当数据是均匀分布的时候折半查找更加优秀,当数据是指数分布的时候斐波那契查找算法更好。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。