• 数据结构 斐波那契查找



    #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])
    */
    


  • 相关阅读:
    [Windows Powershell]-学习笔记(1)
    MyBatis For .NET学习-问题总结
    Zynq学习笔记(1)
    规范的位操作方法
    浮点数转换成字符串函数
    测试卡尔曼滤波器(Kalman Filter)
    关于按键扫描程序的终极讨论
    关于STM8的用户数据空间读写问题
    IPv4分析
    关于STM8空间不足的解决方法
  • 原文地址:https://www.cnblogs.com/hjch0708/p/7554818.html
Copyright © 2020-2023  润新知