ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

数据结构与算法--斐波那契查找

2022-07-30 23:02:42  阅读:132  来源: 互联网

标签:数列 -- mid 斐波 int 查找 那契


斐波那契数列

斐波那契数列,又称黄金分割数列,因数学家莱昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……

在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*),该数列越往后相邻的两个数的比值越趋向于黄金比例值(0.618)


斐波那契查找算法简介

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


算法图解

斐波那契查找原理与二分查找算法和插值查找算法类似,仅仅改变了中间结点(mid)的位置,mid不再是中间或插值得到,而是位于黄金分割点附近

公式 mid= left + F(k-1) - 1,(F代表斐波那契数列,k代表斐波那契数列分割数值的下标)

公式推导

 


代码实现

import java.util.Arrays;

public class FibSearch {

    //假定斐波那契数列大小为20
    public static int maxSize = 20;

    public static void main(String[] args) {
        int[] arr = {1, 8, 10, 89, 1000, 1234};
        System.out.println("index= " + fibSearch(arr, 1000));
    }

    /**
     * 获取一个斐波那契数列
     */
    public static int[] fib() {

        int[] f = new int[maxSize];
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i < maxSize; i++) {
            f[i] = f[i - 1] + f[i - 2];
        }

        return f;
    }

    /**
     * @param arr    数组
     * @param target target需要查找的值
     * @return 返回对应下标,未找到返回-1
     */
    public static int fibSearch(int[] arr, int target) {

        int left = 0;
        int right = arr.length - 1;
        //表示斐波那契分割数值的下标
        int k = 0;
        //存放mid值
        int mid = 0;

        //获取斐波那契数列
        int[] f = fib();

        //获取斐波那契分割数值的下标
        while (right > f[k] - 1) {
            k++;
        }

        //因为f[k],可能大于数组长度,因此需要补齐,不足部分使用0填充
        int[] temp = Arrays.copyOf(arr, f[k]);
        //用数组最后的数值填充temp
        //举例:temp={1, 8, 10, 89, 1000, 1234,0,0} => {1, 8, 48, 88, 89, 899, 1024,1024,1024}
        for (int i = right + 1; i < temp.length; i++) {
            temp[i] = arr[right];
        }

        //使用while循环找到target
        while (left <= right) {
            //得到mid的下标
            mid = left + f[k - 1] - 1;

            if (target < temp[mid]) {
                //继续向数组前部分查找(左边)
                right = mid - 1;
                //为什么是k--
                //说明:
                //1.全部元素=前边元素+后边元素
                //2.f[k] = f[k-1] + f[k-2]
                //因为前面的 f[k-1] 个元素,所以可以继续拆分,f[k-1] = f[k-2] + f[k-3]
                //即再f[k-1]的前面继续查找,k--
                k--;
            } else if (target > temp[mid]) {
                //继续向数组后部分查找(右边)
                left = mid + 1;
                //为什么是k-2
                //说明:
                //1.全部元素=前边元素+后边元素
                //2.f[k] = f[k-1] + f[k-2]
                //3.后面右 f[k-2] 个元素,继续拆分
                //即下次循环 mid = f[k-1-2] - 1
                k -= 2;
            } else {
                //找到。需要确定,返回哪个值
                if (mid <= right) {
                    return mid;
                } else {
                    return right;
                }
            }
        }

        //未找到
        return -1;
    }
}

标签:数列,--,mid,斐波,int,查找,那契
来源: https://www.cnblogs.com/52-IT-y/p/16536070.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有