c 语言 斐波那契搜索(Fibonacci Search)

        给定一个大小为 n 的排序数组 arr[] 和要在其中搜索的元素 x。如果 x 存在于数组中,则返回 x 的索引,否则返回 -1。 
例子: 
输入:  arr[] = {2, 3, 4, 10, 40}, x = 10
输出:  3
元素 x 出现在索引 3 处。

输入:  arr[] = {2, 3, 4, 10, 40}, x = 11
输出:  -1
元素 x 不存在。

        斐波那契搜索是一种基于比较的技术,它使用斐波那契数来搜索排序数组中的元素。
与二分查找的相似之处:
        1、适用于排序数组
        2、分而治之的算法。
        3、具有 Log n 时间复杂度。
与二分查找的区别:
        1、斐波那契搜索将给定数组分成不相等的部分
        2、二分查找使用除法运算符来划分范围。斐波那契搜索不使用 /,而是使用 + 和 -。在某些 CPU 上,除法运算符的成本可能很高。
        3、斐波那契搜索在后续步骤中检查相对较近的元素。因此,当输入数组很大,无法容纳 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) 且
F(n - 1) ≈ (2/3)*F(n)。
算法: 
设要查找的元素为x。
        这个想法是首先找到大于或等于给定数组长度的最小斐波那契数。令找到的斐波那契数为 fib(第 m 个斐波那契数)。我们使用第 (m-2) 个斐波那契数作为索引(如果它是有效索引)。设第(m-2)个斐波那契数为i,我们将arr[i]与x进行比较,如果x相同,则返回i。否则,如果 x 更大,则对 i 之后的子数组进行递归,否则对 i 之前的子数组进行递归。
下面是完整的算法 
设 arr[0..n-1] 为输入数组,要搜索的元素为 x。
        1、找到大于或等于 n 的最小斐波那契数。令这个数字为 fibM [第 m 个斐波那契数]。令其前面的两个斐波那契数为 fibMm1 [(m-1) 个斐波那契数] 和 fibMm2 [(m-2) 个斐波那契数]。
        2、当数组有要检查的元素时: 
                2.1、将 x 与 fibMm2 覆盖范围的最后一个元素进行比较
                2.2、如果x 匹配,则返回索引
                2.3、否则,如果x 小于该元素,则将三个斐波那契变量向下移动两个斐波那契,表示消除剩余数组的大约后三分之二。
                2.4、否则x 大于该元素,将三个斐波那契变量向下移动一位斐波那契。重置索引的偏移量。这些一起表明剩余阵列的大约前三分之一被消除。
        3、由于可能还剩下一个元素可供比较,因此检查 fibMm1 是否为 1。如果是,则将 x 与该剩余元素进行比较。如果匹配,则返回索引。

// C program for Fibonacci Search 
#include <stdio.h> 
  
// 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 Fibonacci 
       Number greater than or equal to n */
    while (fibM < n) { 
        fibMMm2 = fibMMm1; 
        fibMMm1 = fibM; 
        fibM = fibMMm2 + fibMMm1; 
    } 
  
    // Marks the eliminated range from front 
    int offset = -1; 
  
    /* while there are elements to be inspected. Note that 
       we compare arr[fibMm2] with x. When fibM becomes 1, 
       fibMm2 becomes 0 */
    while (fibM > 1) { 
        // Check if fibMm2 is a valid location 
        int 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 */
        else
            return 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); 
  else
    printf("%d isn't present in the array",x); 
    return 0; 

输出
发现于索引: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 调用一次,以此类推。
考虑一下:  

辅助空间: O(1) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/304457.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构-合并两个有效数组

题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;…

意得辑意得辑

你是否也曾遇到过在发表论文时英语写作水平不尽如人意的困境&#xff1f;审稿意见总是指出语言表达不够好&#xff0c;需要找英语母语者修改&#xff1f;不用担心&#xff0c;我和你一样&#xff0c;也曾历经这样的挑战。但是&#xff0c;我找到了一家值得信赖的专业润色机构—…

Apache Incubator Answer 本地开发部署

文章目录 简介Github文档插件部署 Answer开发环境编译项目初始化项目运行项目 简介 一款适合任何团队的问答平台软件。 Apache Incubator Answer是一个开源项目&#xff0c;它是一个用于构建和部署问答系统的框架。该项目是Apache软件基金会的孵化器项目&#xff0c;提供一个…

Lobe UI - 基于 AntDesign 开发的 AIGC Web 应用的开源 UI 组件库

今天推荐一个可以快速开发 ChatGPT UI 界面的组件库&#xff0c;质量很高&#xff0c;拿来就能用。 Lobe UI 是由 lobehub 团队开发的一套 web UI 组件库&#xff0c;和我之前推荐的很多通用型的 UI 组件库不同&#xff0c;Lobe UI 是专门为目前火热的 AIGC 应用开发而打造&am…

一起学习python——基础篇(13)

前言&#xff0c;python编程语言对于我个人来说学习的目的是为了测试。我主要做的是移动端的开发工作&#xff0c;常见的测试主要分为两块&#xff0c;一块为移动端独立的页面功能&#xff0c;另外一块就是和其他人对接工作。 对接内容主要有硬件通信协议、软件接口文档。而涉…

Mybatis-Plus快速入门

MyBatisPlus 通过扫描实体类&#xff0c;并基于反射获取实体类信息作为数据库信息 类名驼峰转下划线作为表名为id的字段作为主键变量名驼峰转下划线作为表的字段名 遵守这些约定MyBatisPlus就会自动生成字段&#xff0c;方便我们快速实现 一、快速入门 起步依赖 MyBatisPlus…

天软特色因子看板 (2024.4 第3期)

该因子看板跟踪天软特色因子A05005(近一月单笔流出金额占比(%)&#xff0c;该因子为近一月单笔流出金额占比(% 均值因子&#xff0c;用以刻画下跌时的 单成交中可能存在的抄底现象 今日为该因子跟踪第3期&#xff0c;跟踪其在SH000852 (中证1000) 中的表现&#xff0c;要点如下…

加州大学欧文分校英语基础语法专项课程01:Word Forms and Simple Present Tense 学习笔记

Word Forms and Simple Present Tense Course Certificate 本文是学习Coursera上 Word Forms and Simple Present Tense 这门课程的学习笔记。 文章目录 Word Forms and Simple Present TenseWeek 01: Introduction & BE VerbLearning Objectives Word FormsWord Forms (P…

vivado 调试核时钟设置指南

调试核时钟设置指南 注释 &#xff1a; 以下章节适用于 7 系列、 UltraScale 和 UltraScale 器件。 Versal 调试核使用基于 AXI 的连接 &#xff0c; 且不受本章中的 时钟设置指南的约束。 Vivado 硬件管理器使用 JTAG 接口来与 Vivado Debug Hub 核进行通信 &#…

Dubbo 序列化

Dubbo 序列化 1、什么是序列化和反序列化 序列化&#xff08;serialization&#xff09;在计算机科学的资料处理中&#xff0c;是指将数据结构或对象状态转换成可取用格式&#xff08;例如存成文件&#xff0c;存于缓冲&#xff0c;或经由网络中发送&#xff09;&#xff0c;…

物联网实验

实验1 基于ZStack光敏传感器实验 1.实验目的 我们通过上位机发指令给协调器&#xff0c;协调器把串口接收到的指令通过Zigbee协议无线发送给带有光敏传感器的终端节点&#xff0c;获取到数据以后把数据返回给上位机&#xff0c;实现无线获取数据的目的。 2.实验设备 硬件&a…

酷开科技一手抓技术,一手抓内容,领跑0TT大屏领域发展

相较于流量池接近饱和的平台而言&#xff0c;OTT市场对于内容创作者是一片新的领域&#xff0c;不同于PC端和移动端&#xff0c;“大屏”设备或许是当下短视频市场不可多得的流量洼地。酷开系统正在用“屏”来为人们构建一个场景智能化的高效率、更便捷、超炫酷的新生活方式。以…

C语言中的数据结构--链表的应用1(2)

前言 上一节我们学习了链表的概念以及链表的实现&#xff0c;那么本节我们就来了解一下链表具体有什么用&#xff0c;可以解决哪些实质性的问题&#xff0c;我们借用习题来加强对链表的理解&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 单链表相关经典算法O…

乡村智慧化升级:数字乡村打造农村生活新品质

目录 一、乡村智慧化升级的内涵与意义 二、乡村智慧化升级的具体实践 1、加强农村信息基础设施建设 2、推广智慧农业应用 3、提升乡村治理智慧化水平 4、丰富智慧乡村生活内容 三、数字乡村打造农村生活新品质的成果展现 1、农业生产效率与质量双提升 2、农民收入与消…

【笔试】02

TCP TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议 它能够提供以下服务&#xff1a; 可靠传输 通过序列号、确认应答、重传机制等确保数据完整、准确地从发送端传输到接收端。 三次握手&#xff1a; 点对点全双工面向字节流…

【计算机毕业设计】校园网书店系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

JDK版本升级后连不上MySQL数据库的问题

1. 问题描述 用户在将 JDK 版本从 8 升级到 11 后&#xff0c;发现应用无法连接到 MySQL 数据库&#xff0c;出现连接超时或连接被拒绝的错误。 例如出现如下报错信息&#xff1a; 可能原因&#xff1a; JDBC驱动版本不兼容&#xff1a; 新的 JDK 11 可能需要使用更高版本的 My…

Flutter第六弹 基础列表ListView

目标&#xff1a; 1&#xff09;Flutter有哪些常用的列表组建 2&#xff09;怎么定制列表项Item&#xff1f; 一、ListView简介 使用标准的 ListView 构造方法非常适合只有少量数据的列表。我们还将使用内置的 ListTile widget 来给我们的条目提供可视化结构。ListView支持…

Canal介绍原理及安装

Canal 扩展篇 1.Canal介绍、 链接: https://github.com/alibaba/canal Canal 主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费&#xff0c;工作原理如下&#xff1a; Canal 模拟 MySQL slave 的交互协议&#xff0c;伪装自己为 MySQL slave &am…

Redis中的集群(五)

集群 在集群中执行命令 MOVED错误。 当节点发现键所在的槽并非由自己负责处理的时候&#xff0c;节点就会向客户端返回一个MOVED错误&#xff0c;指引客户端转向至正在负责槽的节点&#xff0c;MOVED错误的格式为: MOVED <slot> <ip>:<port>其中slot为键…