zoukankan      html  css  js  c++  java
  • 查找算法-Fibonacci查找

    斐波那契查找是一种在有序表中高效查找指定元素的算法,比折半查找要复杂一些,主要复杂在要多做不少准备工作。下面看它的工作流程:

            1.计算并保存一个斐波那契序列的数组,方便以后取值。数组名记为f,例如f[1]=1,f[2]=1,f[3]=2,f[4]=3,f[5]=5,f[6]=8,f[7]=13,f[8]=21

            2.把有序数组的长度扩充到a.length=f[k]-1,k是满足条件的最小值,比如数组长度为13,那么就把它长度扩充到f[8]-1=20,所有在末尾添加的扩充元素都是原数组最后一个元素的复制品

            3.找到mid元素,不断进行二分比较,直到找到目标元素为止,这一步的做法与折半查找一模一样,仅仅是计算mid的公式从(low+high)/2改为low+(f[k-1]-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),这样递归分割下去就 能不断的缩小区间直至找到目标。

     

    #include <stdio.h>
    #define LEN 9
    #define MAXSIZE 100
    
    int F[50];//fibonacci数列
    //构造fibonacci数列
    void FibonacciArray(int * a){
        int i;
        a[0]=1;
        a[1]=1;
        for(i=2; i<50; i++){
            a[i]=a[i-1]+a[i-2];
        }
    }
    
    //进行fibonacci查找,返回0即查找失败,否则返回找到的下标
    int FibonacciSearch(int * a,int n,int key){
        int k=0,i;
        int mid,low=1,high=n;
        while(n>F[k]-1)
            k++;//确定初始k值
        
        for(i=n+1; i<=F[k]-1; i++ ){
            a[i]=a[n];    //补全a[n+1]到a[F[k]-1],使之都==a[n]
        }
        //开始查找
        while(low<=high){//注意
            mid=low+F[k-1]-1;
            if(a[mid]>key){//如果中间值比要查找的值大
                high=mid-1;
                k=k-1;
            }else if(a[mid]<key){
                    low=mid+1;
                    k=k-2;
                }else{//a[mid]==key
                    if(mid<=n) return mid;
                        else if(mid>n)//说明找到的下标在原来填补的位置上,是和a[n]相同的,所以返回n
                            return n;
                }
                    
        }
        return 0;//返回0,即key不在数组a中
    }
    int main(){
    
    int a[LEN+1]={0,8,23,45,78,89,25,68,47,59};//设首位为哨兵
    int arr[MAXSIZE]={0};//设一个足够大的数组,代入函数计算
    for(int i=0; i<LEN+1; i++){
        arr[i]=a[i];
    }
    
    int result;
    int key=59;
    FibonacciArray(F);//返回[1,1,2,3,5,...]
    //printf("%d",F[7]);
    result=FibonacciSearch(arr,LEN,key);
    if(result!=0){
        printf("%d存在数组a中,等于a[%d]
    ",key,result);
    }else
        printf("数组a中不存在%d
    ",key);
    
    return 0;
    }

     结果:

    之前写的时候返了一个错误,while(low<=high)小于等于写成了<;

    参考:

    [1]大话数据结构,p.303-304

    [2]http://blog.csdn.net/lzdidiv/article/details/59784694

  • 相关阅读:
    POJ1661 Help Jimmy
    POJ2533 Longest ordered subsequence
    数字三角形
    第四章 指令系统
    栈和队列
    第三章 存储器的层次结构
    线性表—概念总结及代码示例
    数据的表示和运算
    计算机系统概述
    树-概念性总结及代码示例
  • 原文地址:https://www.cnblogs.com/Allen-win/p/7364414.html
Copyright © 2011-2022 走看看