查找算法之费氏搜寻法
创始人
2025-05-30 20:15:24

给定一个大小为n的排序数组arr[],并在其中搜索一个元素x。如果x在数组中,则返回x的下标,否则返回-1。

费氏搜索是一种基于比较的技术,它使用斐波那契数搜索排序数组中的元素。

与二分搜索的相似之处:

  1. 适用于排序数组

  1. 分治算法。

  1. 时间复杂度为Log n。

与二分查找的区别:

  1. 斐波那契搜索将给定数组分割成不相等的部分

  1. 二分搜索使用除法运算符来分割范围。斐波那契搜索不使用/,而是使用+和-。除法运算符在某些cpu上可能代价很高。

  1. 斐波那契搜索在后续步骤中检查相对较近的元素。因此,当输入数组很大,无法装入CPU缓存甚至RAM时,斐波那契搜索就很有用了。

背景

斐波那契数被递归定义为 F(n) = F(n-1) + F(n-2), F(0) = 0, F(1) =

1. 前几个斐波那契数是 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …

观测

下面的观察结果用于范围消除,因此用于O(log(n))复杂度。

F(n - 2) ≈ (1/3)*F(n) and

F(n - 1) ≈ (2/3)*F(n).

算法

设搜索的元素为x。

其思想是首先找到大于或等于给定数组长度的最小斐波那契数。让找到的斐波那契数为fib(第m个斐波那契数)。我们使用(m-2)次斐波那契数作为索引(如果它是一个有效的索引)。设(m-2)第1个斐波那契数为i,我们比较arr[i]和x,如果x相同,我们返回i。否则如果x更大,我们在i之后递归子数组,否则在i之前递归子数组。

下面是完整的算法

让arr [0 . .N-1]为输入数组,要搜索的元素为x。

  1. 找出大于或等于n的最小斐波那契数。设此数为fibM[第m个斐波那契数]。设它前面的两个斐波那契数为fibMm1 [(m-1)第th斐波那契数]和fibMm2 [(m-2)第th斐波那契数]。

  1. 当数组有要检查的元素时:

  1. 将x与fibMm2覆盖的范围的最后一个元素进行比较

  1. 如果 x 匹配, return 索引

  1. 如果x小于该元素,则将三个斐波那契变量向下移动两个斐波那契,表示消除大约后面三分之二的剩余数组。

  1. 否则x大于元素,将三个斐波那契变量向下移动一个斐波那契。将偏移量重置为索引。这些组合在一起表明消除了大约前三分之一的剩余阵列。

  1. 由于可能剩下一个元素进行比较,因此检查fibMm1是否为1。如果是,将x与剩余的元素进行比较。如果匹配,返回索引。

以下是C代码的实现源码

// C program for Fibonacci Search
#include // Utility function to find minimum of two elements
int min(int x, int y) { return (x <= y) ? x : y; }/* Returns index of x if present, else returns -1 */
int fibMonaccianSearch(int arr[], int x, int n)
{/* Initialize fibonacci numbers */int fibMMm2 = 0; // (m-2)'th Fibonacci No.int fibMMm1 = 1; // (m-1)'th Fibonacci No.int fibM = fibMMm2 + fibMMm1; // m'th Fibonacci/* fibM is going to store the smallest FibonacciNumber greater than or equal to n */while (fibM < n) {fibMMm2 = fibMMm1;fibMMm1 = fibM;fibM = fibMMm2 + fibMMm1;}// Marks the eliminated range from frontint offset = -1;/* while there are elements to be inspected. Note thatwe compare arr[fibMm2] with x. When fibM becomes 1,fibMm2 becomes 0 */while (fibM > 1) {// Check if fibMm2 is a valid locationint i = min(offset + fibMMm2, n - 1);/* If x is greater than the value at index fibMm2,cut the subarray array from offset to i */if (arr[i] < x) {fibM = fibMMm1;fibMMm1 = fibMMm2;fibMMm2 = fibM - fibMMm1;offset = i;}/* If x is greater than the value at index fibMm2,cut the subarray after i+1 */else if (arr[i] > x) {fibM = fibMMm2;fibMMm1 = fibMMm1 - fibMMm2;fibMMm2 = fibM - fibMMm1;}/* element found. return index */elsereturn i;}/* comparing the last element with x */if (fibMMm1 && arr[offset + 1] == x)return offset + 1;/*element not found. return -1 */return -1;
}/* driver function */
int main(void)
{int arr[]= { 10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100,235};int n = sizeof(arr) / sizeof(arr[0]);int x = 235;int ind = fibMonaccianSearch(arr, x, n);
if(ind>=0)printf("Found at index: %d",ind);
elseprintf("%d isn't present in the array",x);return 0;
}

输出

Found at index: 11

说明:

让我们用下面的例子来理解这个算法:

举例假设:基于1的索引。目标元素x是85。数组长度n = 11。

大于或等于11的最小斐波那契数是13。根据我们的例子,fibMm2 = 5, fibMm1 = 8, fibM = 13。

另一个实现细节是偏移量变量(零初始化)。它从前面开始标记已消除的范围。我们会不时更新。

现在,由于偏移值是一个指标,包括它在内的所有指标和低于它的指标都被消除了,所以只有向它添加一些东西才有意义。由于fibMm2标记了大约三分之一的数组,以及它标记的索引,确保是有效的,我们可以将fibMm2添加到offset,并检查索引i = min(offset + fibMm2, n)处的元素。

时间复杂度分析

当我们的目标在数组的较大(2/3)部分时,最坏情况将发生,因为我们继续寻找它。换句话说,我们每次都要消除数组中较小的(1/3)部分。我们对n调用一次,然后是(2/3)n,然后是(4/9)n,如此类推。

相关内容

热门资讯

数据结构---队列 专栏:数据结构 个人主页:HaiFan. 专栏简介:这里是...
数字操作方法 系列文章目录 前端系列文章——传送门 JavaScript系列文章——传送门 文章目录系列文章目录...
Cartesi 2023 年 ... 查看 Cartesi Machine、Cartesi Rollups 和 Noether 的更新正在...
JavaWeb——jsp概述入... JSP定义:  在如下一个jsp文件里面有如下的代码  <%@ page content...
一切喜怒哀乐都来自于你的认知 01 有个学子,准备出国,父母请来清华的教授宁向东。请问教授࿱...
JAVA并发编程——synch... 引言         Java语言为了解决并发编程中存在的原子性、可见性和有序性问题,...
git学习----3.21 未... 文章目录前言Git :一个分布式版本控制工具目标一、概述1.1 开发中的实际场景1.2...
Qt优秀开源项目之十七:QtP... QtPromise是Promises/A+规范的Qt/C++实现。该规范的译...
【前端八股文】JavaScri... 文章目录Set概念与arr的比较属性和方法并集、交集、差集Map概念属性和方法String用索引值和...
海康硬盘录像机接入RTSP/o... EasyNVR安防视频云服务平台可支持设备通过RTSP/Onvif协议接入平台,能提供...
在混合劳动力时代如何避免网络安... 在混合劳动力时代如何避免安全网络风险 三年多来,混合工作一直是工作生活中不可或缺的一...
2023还不懂Jmeter接口... 这里介绍的Jmeter接口测试的的实战,如果文章内容没遇看懂的话,我这边...
基于4G/5G弱网聚合的多链路... 基于4G/5G多卡聚合(弱网聚合)的智能融合通信设备技术亮点 增强带宽提供可靠连接 通过将多个有线和...
如何使用Synplify综合v... 文章目录使用Synplify综合的好处synplify的教程方法1(无效)...
2023年全国最新高校辅导员精... 百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等ÿ...
2022年18个值得期待的Le... 有数百个独特的LearnDash附加组件,您可能很难选择您的LearnDash LMS...
【java基础】Stream流... 文章目录基本介绍流的创建流的各种常见操作forEach方法filter方法map方法peek方法fl...
javaweb高校行政办公自动... 本课题基于我国高校管理信息化建设现状,结合在实际工作中所遇到的问题和收获,...
一款专门为自动化测试打造的集成... 你好,我是不二。 随着行业内卷越来越严重,自动化测试已成为测试工程师的...
【go-zero】golang... 一、casbin 概览 1、casbin基本了解 casbin的GitHub:https://git...
现在开发低代码平台算晚吗? 现在开发低代码平台算晚吗?作为低代码的亲戚——零代码厂商,这篇就以“厂商...
【JavaWeb】书城项目(2... 222.书城项目-第三阶段:修改所有html页面为jsp页面 改成jsp页面之后&#x...
基于jeecgboot的大屏设...      通过前面设计好数据源后,就要进行数据集的设计了。      一、还是在onl...
Linux命令小技巧:显示文件... 工作中会有很多千奇百怪的需求,比如:如何在 Linux 命令行中快速找到...
【找工作】-- 大数据工程师找... 目录 1.前言 2.找工作的理论知识 2.1 分析个人特征 2.1.1 你自身优势是什么?
C++基础算法④——排序算法(... 排序算法 1.插入排序 2.桶排序 1.插入排序 基本思想:将初始数据分为有序部分和...
nginx快速入门.跟学B站n... nginx快速入门.跟学B站nginx一小时精讲课程笔记nginx简介及环境准备nginx简介环境准...
ORACLE存过互相调用之间事... 今天在问答区看到一个问题是 假如有procedureA、procedureB和procedureC&...
基于java中Springbo... 基于java中Springboot框影视影院订票选座管理系统 开发语言:Java 框...
CVE-2018-18086 最近闲来无事,看到青少年CTF平台,感觉对新手还是比较友好的࿰...