版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37345402/article/details/87709299
二分查找每次查找时会在查找范围上限的中点处比较,而斐波那契查找则在查找范围上限的一个斐波那契分割点上进行查找。
斐波那契查找的优点是在确定下一个比对元素时,仅用加、减就可以计算得出,比二分查找的除法要节省时间。
- 第一,计算并保存一个斐波那契序列的数组,fib[1]=1,fib[2]=1,fib[3]=2,fib[4]=3,fib[5]=5。
- 第二,将有序数组的长度扩充到 n=fib[k]-1,k是满足条件的最小值,所有在末尾添加的扩充元素都是原数组最后一个元素的copy。
- 第三,与折半查找一样,找到mid元素,不断进行二分比较,仅是mid=(low+high)/2变为mid=low+(f[k-1]-1),直到找到key为止。
将k值与第F(k-1)位置的记录进行比较(即mid=low+F(k-1)-1)
1)当key=a[mid]时,查找成功;
2)当key<a[mid]时,新的查找范围是第left个到第mid-1个,此时范围个数为fib[k-1] - 1个,故范围为[left,fib[k - 1] - 1];
3)当key>a[mid]时,新的查找范围是第mid+1个到第right个,此时范围个数为fib[k-2] - 1个,故范围为[fib[k - 2] - 1,right]。
关于 n=fib[k]-1:数组中的元素个数是fib(k)-1个,使用mid值进行分割又用掉一个,那么剩下fib(k)-2个。正好分给两个子序列,每个子序列的个数分别是fib(k-1)-1与fib(k-2)-1个
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
void Fibo(int *fib){
fib[0]=0;fib[1]=1;
for(int i=2;i<MAXSIZE;i++){
fib[i]=fib[i-1]+fib[i-2];
}
}
int Fibonacci_Search(int *a,int n,int key){
int left,right,mid,k=0;
left=0;
right=n-1;
int fib[MAXSIZE];
Fibo(fib);
while(n>fib[k]-1){//计算n位于斐波那契的位置
k++;
}
int *temp;
temp=(int *)malloc((fib[k]-1)*sizeof(int));
for(int i=0;i<n;i++){
temp[i]=a[i];
}
for(int i=n;i<fib[k]-1;i++){
temp[i]=a[n-1];
}
while(left<=right){
mid=left+fib[k-1]-1;
if(key<temp[mid]){
right=mid-1;
k-=1;//mid以左的部分长度为fib[k-1]-1;
}else if(key>temp[mid]){
left=mid+1;
k-=2;//mid以右的部分长度为fib[k-2]-1;
}else{//key==temp[mid]说明mid为查到的位置
if(mid<n){
return mid;
}else{
return n-1;//mid>=n说明是扩展的数值
}
}
}
return -1;
}
int main(){
int a[MAXSIZE];
for(int i=0;i<6;i++){
scanf("%d",&a[i]);
}
printf("2所在的位序为%d\n",Fibonacci_Search(a,6,2));
return 0;
}