数据结构 斐波那契查找


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<iostream>
#include<cmath>
using namespace std;
int f[1005];

void init()
{
    int i,j;
    f[0]=0;
    f[1]=1;
    for(i=2; i<1000; i++)
        f[i]=f[i-1]+f[i-2];
    //以上进行斐波那契数组初始化
}

int Fibonacci_Search(int *a,int n,int key)
{
    init();
    int low=0,high=n-1,mid,k=0;//注意下标
    int i,j;
    while(n>f[k]-1)k++;//这里执行完之后m,f[k]-1>n
    for(i=n; i<f[k]-1; i++)
        a[i]=a[n-1];//扩展到f[k]-1;
    /*

            为什么需要把数组长度扩充到f[k]-1而不是f[k]或者f[k+1]?这是为了能正确递归计算mid值,
            看下图可发现 f[k]-1 = (f[k-1] + f[k-2]) - 1 = (f[k-1]-1) + 1 + (f[k-2]-1),
            中间的1就是我们二分的锚点mid,如果目标在左区,数组长度就缩到(f[k-1]-1),如果在右区,
            数组长度就缩到(f[k-2]-1),否则就等于mid完成查找。而(f[k-1]-1)又能拆成(f[k-2]-1)+1+(f[k-3]-1),
            这样递归分割下去就能不断的缩小区间直至找到目标。
            也也就是说:如果一个有序表的元素个数为n,并且n正好是(某个斐波那契数 - 1),即n=F[k]-1时,才能用斐波那契查找法。
            如果有序表的元素个n不等于(某个斐波那契数 - 1),即n≠F[k]-1,这时必须要将有序表的元素扩展到大于n的那个斐波那契数 - 1
    */
    // for(i=0;i<f[k]-1;i++)
    //   printf("%d ",a[i]);
    //printf("
");
    while(low<=high)
    {
        mid=low+f[k-1]-1;
        //low就是此时的左边下标,也就是黄金分割的起始点,f[k-1]-1代表个数,并不是所谓的数组下标从0开始
        //这里可以对比二分查找理解,其实low high下标变化完全一样,不一样的就是mid值的变化,斐波那契是采用黄金分割
        //而二分查找是采用对半分割
        if(a[mid]>key)
        {
            high=mid-1;
            k=k-1;
        }
        else if(a[mid]<key)
        {
            low=mid+1;
            k=k-2;
        }
        else
        {
            if(mid<=n)return mid;
            else return n;
        }
    }
    return -1;
}

int main()
{
    int i,j,k,n;
    int a[10000];
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=0; i<n; i++)scanf("%d",&a[i]);
        printf("%d
",Fibonacci_Search(a,11,k));
    }
    return 0;
}
/*
11 0
0 1 16 24 35 47 59 62 73 88 99
11 88
0 1 16 24 35 47 59 62 73 88 99
11 1
0 1 16 24 35 47 59 62 73 88 99
*/
/*
斐波那契查找的核心是:
  1)当key=a[mid]时,查找成功;
  2)当key<a[mid]时,新的查找范围是第low个到第mid-1个,此时范围个数为F[k-1] - 1个,即数组左边的长度,所以要在[low, low+F[k - 1] - 1]范围内查找;
  3)当key>a[mid]时,新的查找范围是第mid+1个到第high个,此时范围个数为F[k-2] - 1个,即数组右边的长度,所以要在[(mid+1),(mid+1)+F[k - 2] - 1]范围内查找。
  联系黄金分割比例来分析,黄金分割分成两部分,一段长(即是发f[k-1]),一段短(f[k-2])
*/


原文地址:https://www.cnblogs.com/hjch0708/p/7554818.html