斐波拉契查找------减1操作详解

参考博客:
1.斐波那契查找原理详解与实现
2.斐波那契查找(黄金分割法查找)(仅使用加减实现的二分查找)

斐波拉契数列

斐波那契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、••••,在数学上,斐波那契被递归方法如下定义:F(1)=1,F(2)=1,F(n)=f(n-1)+F(n-2) (n>=2)。该数列越往后相邻的两个数的比值越趋向于黄金比例值(0.618)。

基本思想

斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的。在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为Fn,完成后进行斐波那契分割,即F[n]个元素分割为前半部分F[n-1]个元素后半部分F[n-2]个元素,找出要查找的元素在那一部分并递归,直到找到。

程序示例

//a为要查找的数组,n为要查找的数组长度,key为要查找的关键字
int Fibonacci_Search(int *a, int n, int key)  
{
    int low = 0, k = 0;
    int high = n - 1;
    int F[max_size];
    Fibonacci(F);       //构造一个斐波那契数组F 
    while(n > F[k]-1)   //计算n位于斐波那契数列的位置
        ++k;

    int* temp = new int[F[k]-1];    //将数组a扩展到F[k]-1的长度
    memcpy(temp, a, n*sizeof(int));

    for(int i = n; i < F[k]-1; ++i)
        temp[i] = a[n-1];

    while(low <= high)
    {
        int mid = low + F[k-1] - 1;
        if(key < temp[mid])
        {
            high = mid - 1;
            k   -= 1;
        }
        else if(key > temp[mid])
        {
            low = mid + 1;
            k  -= 2;
        }
        else
        {
            if(mid < n) return mid; //若相等则说明mid即为查找到的位置
            else        return n-1; //若mid>=n则说明是扩展的数值,返回n-1
        }
    }
    delete[] temp;
    return -1;
}

首先初始化一个拥有max_size大小的斐波拉契数组F,然后寻找一个略大于数组a长度的斐波拉契数F[k],即n <= F[k]-1,n < F[k]。而后申请了一个F[k]-1大小的数组temp,并初始化。
我们从上一段话中看到,程序中反复地提到一个尺寸量F[k]-1。现就此提出两个问题: ①. 为什么要查找这样一个k,使得n <= F[k]-1,而非n <= F[k]?
②. 为什么另申请的数组temp的长度为F[k]-1,而非F[k]?
这样做的目的就是为了钳位这样一个k,使得数组的长度等于F[k]-1,而F[k]-1 = F[k-1]-1 + mid位 + F[k-2]-1。例如,k=5的时候,F[k]-1 = 4,F[k-1]-1 = 2,,F[k-2]-1 = 1,即满足4 = 2 + mid位 + 1。这样就总能找到一个mid使得其前半部分序列和后半部分序列满足:

                 F[x]-1x可以为1,2,3...)

这样处理之后(即减1操作)就总能满足递归的条件。
下面继续程序的讲解。temp初始化之后,进入循环体。在循环体内,先对mid位上的值与key值进行比较,若key < temp[mid],则将F[k]-1长数组的前半部分F[k-1]-1作为新的递归序列,若key > temp[mid],就使用后半部分F[k-2]-1,如此就实现了二分。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值