查找-斐波那契查找

参考:https://www.cnblogs.com/yongh/p/9232742.html#_label1_2

源码:https://github.com/sunrui849/selectAlgorithm

目录:顺序查找

二分查找

插值查找

斐波那契查找

分块查找

哈希查找

二叉树查找

红黑树查找

斐波那契查找

斐波那契数列如下所示:

  斐波那契查找原理与前两种相似,仅仅改变了中间结点(mid)的位置,mid不再是中间或插值得到,而是位于黄金分割点附近,即mid=low+F(k-1)-1(F代表斐波那契数列),如下图所示:

 

  对F(k-1)-1的理解:

  由斐波那契数列 F[k]=F[k-1]+F[k-2] 的性质,可以得到 (F[k]-1)=(F[k-1]-1)+(F[k-2]-1)+1 。该式说明:只要顺序表的长度为F[k]-1,则可以将该表分成长度为F[k-1]-1F[k-2]-1的两段,即如上图所示。从而中间位置为mid=low+F(k-1)-1

  但顺序表长度n不一定刚好等于F[k]-1,所以需要将原来的顺序表长度n增加至F[k]-1。这里的k值只要能使得F[k]-1恰好大于或等于n即可。

  时间复杂度:最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n)。

顺序表长度增加后,新增的位置(从n+1到F[k]-1位置),都赋为n位置的值即可。

代码实现

 /**
     * 斐波那契数列递归法
     * @param num
     * @return
     */
    public static int getFibonacciValue(int num){
        if (num == 0){
            return 0;
        }else if (num == 1){
            return 1;
        }
        return getFibonacciValue(num-1) + getFibonacciValue(num-2);
    }

    /**
     * 斐波那契数列非递归法
     * @param num
     * @return
     */
    public static int getFibonacciValue2(int num){
        int v1 = 0;
        int v2 = 1;

        if (num == 0){
            return v1;
        }else if(num == 1){
            return v2;
        }

        int value = 0;
        for (int i = 2;i <= num; i++){
            value = v1 + v2;
            v1 = v2;
            v2 = value;
        }
        return value;
    }

    private static int select(List<Integer> list, int selectValue) {
        if (list == null || list.isEmpty()){
            return -1;
        }

        int listSize = list.size();
        //获取斐波那契数下标
        int index = 0;
        while (getFibonacciValue(index)-1 < listSize){
            index++;
        }

        int endValue = list.get(listSize-1);
        //将list扩容为 F(n)-1 长度  即存在某一个斐波那契数减一大于集合的长度,最小的那个斐波那契数。
        for (int i = listSize;i < getFibonacciValue(index) - 1;i++){
            list.add(endValue);
        }

        int low = 0;
        int height = list.size() - 1;
        while (height >= low){
            //中间值左边为f(n-2)-1个值,右边为f(n-1)-1个值,一共f(n)-1个值
            int middleIndex = low + getFibonacciValue(index-1) - 1;
            if (list.get(middleIndex) > selectValue){
                height = middleIndex-1;
                index = index - 1;
            }else if (list.get(middleIndex) < selectValue){
                low = middleIndex+1;
                index = index - 2;
            }else {
                if (middleIndex >= listSize){
                    return listSize - 1;
                } else {
                    return middleIndex;
                }
            }
        }

        return -1;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值