查找算法 —— 斐波拉契查找法

news2024/11/16 10:34:34

一、介绍

        斐波拉契查找法是以分割范围进行查找的,分割的方式是按照斐波拉契级数的方式来分割。好处是:只用到加减运算,计算效率较高一些。

       要使用斐波拉契查找首先需要定义一颗斐波拉契查找树,建立规则如下:

       1.斐波拉契树的左右子树均为斐波拉契树。

       2.当数据个数n确定时,若想确定斐波拉契树的层数k值,就必须找到一个最小的K值,使得斐波拉契层数的Fib(k+1)>= n+1.

       3.斐波拉契树的树根一定是一个斐波拉契树,且子节点与父节点差值的绝对值为斐波拉契数。

       4.当k>=2时,斐波拉契树的树根为Fib(k),左子树为(k-1)层斐波拉契树(其树根为Fib(k-1)),

右子树为(k-2)层斐波拉契树(其树根为Fib(k) + Fib(k-2))。

       5.若n+1的值不为斐波拉契数的值,则可以找出存在一个m使用Fib(k+1)-m = n+1,m=Fib(k+1)-(n+1),再按斐波拉契树的建立原则完成斐波拉契树的建立,最后斐波拉契树的各节点减去差值m即可,并把小于1的节点去掉。

      可以先罗列一部分斐波拉契数的值,如下:

 Fib(0) = 0, Fib(1) = 1, Fib(2) = 1, Fib(3) =2, Fib(4) = 3,

 Fib(5) = 5, Fib(6) = 8, Fib(7) = 13,  Fib(8) = 21, Fib(9) = 34,

      接下来第一种情况时n+1的值是斐波拉契数的值,假设就是数1~33,也就是n=33,那么n+1 = 34,可以根据Fib(k+1) >= n+1 得出 k的值为8,则可以建立斐波拉契树,如下:       

  第二种情况就是n+1的值不是斐波拉契数的值,假设n=10,那么n+1 =11,不是斐波拉契数,按照第五条规则,可以找出一个值m,使Fib(k+1) - m = n+1成立,则Fib(k+1)=13,则m=2, k=6,按照规则建立的斐波拉契树如下:

各节点减去m,并把小于1的节点去掉之后得到

斐波拉契查找法步骤首先将要查找的数与树根Fib(k)比较,如果相等这个数就是Fib(k),如果比Fib(k)小则,数在1到Fib(k)-1之间,如果比Fib(k)大,则这个数在Fib(k)+1到Fib(k+1)-1之间。

二、建立Fib树代码

1.首先先生成Fib数储存起来,避免每次查找都要计算一遍:

void FibCalc(int n)
{   
    fibls.Add(0);
    for (int i = 1; i < n; i++)
    {
        if (i < 3)
        {
            fibls.Add(1);
        }
        else
        {
            fibls.Add(fibls[i-1] + fibls[i-2]);
        } 
    }
}

2.然后判断一个数是不是Fib数并且找到一个比这个数大或者相等的Fib数

 bool LookUpFibAndIsFib(int val, out int ksum1)
 {
     ksum1 = -1;
     if (val < 0)
     {
         Debug.LogError("输入的值不能小于0");
         return false;
     }
        
     for (int i = 0; i < fibls.Count; i++)
     {
         if (val == fibls[i])
         {
             ksum1 = i;
             return true;
         }
         else if(val < fibls[i])
         {
             ksum1 = i;
             return false;
         }
     }
     Debug.LogError("没有匹配到K");
     return false;
 }

 3,生成Fib树

  void GenerateFibTree(Node node, int k,int val)
  {
      if (k - 2 < 0) return;
      int fibNum = node.Data - fibls[k - 2];
      

      if (fibNum == node.Data) return;

      if (node.Data != 1)
      {
          node.LeftNode = new Node();
          node.LeftNode.Data = fibNum;
          node.LeftNode.PNode = node;
      }

      int fibNumR = node.Data + fibls[k - 2];
      if (fibNum > 1 && fibNumR != root.Data)
      {

          if (fibNumR != node.PNode.Data || node.PNode == null)
          {
              if (node.PNode.PNode != null && fibNumR != node.PNode.PNode.Data)
              {
                  node.RightNode = new Node();
                  node.RightNode.Data = fibNumR;
                  node.RightNode.PNode = node;
              }
              if (node.PNode.PNode == null)
              {
                  node.RightNode = new Node();
                  node.RightNode.Data = fibNumR;
                  node.RightNode.PNode = node;
              }
          }
      }

      if (node.LeftNode != null)
          GenerateFibTree(node.LeftNode, k - 1, val);
      if (node.RightNode != null)
          GenerateFibTree(node.RightNode, k - 2, val);
  }

 4.在需要减去m的情况下:

 void FibTreeMinusM(int m,Node node)
 {
     if (node.LeftNode != null)
     {
         node.LeftNode.Data -= m;
         FibTreeMinusM(m, node.LeftNode);
         if (node.LeftNode.Data < 1)
             node.LeftNode = null;
     }
     if (node.RightNode != null)
     {
         node.RightNode.Data -= m;
         FibTreeMinusM(m, node.RightNode);
         if (node.RightNode.Data < 1)
             node.RightNode = null;
     }
 }

5.最后按照输入的数值生成Fib树

   void FibLookUpArithmetic(int val)
   {
       int ksum1 = 0;
       if (LookUpFibAndIsFib(val+1, out ksum1))
       {
           int k = ksum1 - 1;
           InitGenerateFibTree(k,val);
       }
       else
       {
           int k = ksum1 - 1;
           InitGenerateFibTree(k, val);
           int m = fibls[ksum1] - (val + 1);
           root.Data -= m;
           FibTreeMinusM(m, root);
       }
   }

 完整代码:

using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.Rendering;

public class LookUpArithmetic : MonoBehaviour
{
    List<int> fibls;
    Node root;
    void Start()
    {
        fibls = new List<int>(30);
        FibCalc(30);
        FibLookUpArithmetic(10);
    }

    void FibLookUpArithmetic(int val)
    {
        int ksum1 = 0;
        if (LookUpFibAndIsFib(val+1, out ksum1))
        {
            int k = ksum1 - 1;
            InitGenerateFibTree(k,val);
        }
        else
        {
            int k = ksum1 - 1;
            InitGenerateFibTree(k, val);
            int m = fibls[ksum1] - (val + 1);
            root.Data -= m;
            FibTreeMinusM(m, root);
        }
    }

    bool LookUpFibAndIsFib(int val, out int ksum1)
    {
        //首先判断是否是一个Fbi数和找到一个Fbi数两步可以合并为一步
        ksum1 = -1;
        if (val < 0)
        {
            Debug.LogError("输入的值不能小于0");
            return false;
        }
           
        for (int i = 0; i < fibls.Count; i++)
        {
            if (val == fibls[i])
            {
                ksum1 = i;
                return true;
            }
            else if(val < fibls[i])
            {
                ksum1 = i;
                return false;
            }
        }
        Debug.LogError("没有匹配到K");
        return false;
    }

    void FibCalc(int n)
    {   
        fibls.Add(0);
        for (int i = 1; i < n; i++)
        {
            if (i < 3)
            {
                fibls.Add(1);
            }
            else
            {
                fibls.Add(fibls[i-1] + fibls[i-2]);
            } 
        }
    }

    void InitGenerateFibTree(int k, int val)
    {
        root = new Node();
        root.Data = fibls[k];
        root.LeftNode = new Node();
        root.LeftNode.Data = fibls[k] - fibls[k - 2];
        root.LeftNode.PNode= root;
        GenerateFibTree(root.LeftNode, k - 1, val);
        root.RightNode = new Node();
        root.RightNode.Data = fibls[k] + fibls[k - 2];
        root.RightNode.PNode = root;
        GenerateFibTree(root.RightNode, k - 2, val);
    }

    void GenerateFibTree(Node node, int k,int val)
    {
        if (k - 2 < 0) return;
        int fibNum = node.Data - fibls[k - 2];
      

        if (fibNum == node.Data) return;

        if (node.Data != 1)
        {
            node.LeftNode = new Node();
            node.LeftNode.Data = fibNum;
            node.LeftNode.PNode = node;
        }

        int fibNumR = node.Data + fibls[k - 2];
        if (fibNum > 1 && fibNumR != root.Data)
        {

            if (fibNumR != node.PNode.Data || node.PNode == null)
            {
                if (node.PNode.PNode != null && fibNumR != node.PNode.PNode.Data)
                {
                    node.RightNode = new Node();
                    node.RightNode.Data = fibNumR;
                    node.RightNode.PNode = node;
                }
                if (node.PNode.PNode == null)
                {
                    node.RightNode = new Node();
                    node.RightNode.Data = fibNumR;
                    node.RightNode.PNode = node;
                }
            }
        }

        if (node.LeftNode != null)
            GenerateFibTree(node.LeftNode, k - 1, val);
        if (node.RightNode != null)
            GenerateFibTree(node.RightNode, k - 2, val);
    }

    void FibTreeMinusM(int m,Node node)
    {
        if (node.LeftNode != null)
        {
            node.LeftNode.Data -= m;
            FibTreeMinusM(m, node.LeftNode);
            if (node.LeftNode.Data < 1)
                node.LeftNode = null;
        }
        if (node.RightNode != null)
        {
            node.RightNode.Data -= m;
            FibTreeMinusM(m, node.RightNode);
            if (node.RightNode.Data < 1)
                node.RightNode = null;
        }
    }
}

class Node
{
    public Node LeftNode;
    public Node RightNode;
    public int Data;
    public Node PNode = null;
}

如有不足之处,欢迎指正。

参考书籍:

清华大学出版社-图书详情-《图解数据结构--使用C#》 (tsinghua.edu.cn)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

德国鞋履品牌【Birkenstock】申请15亿美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;德国鞋履品牌【Birkenstock】近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为&#xff08;BIRK&#xff09;,Birkens…

Vue-1.9工程化开发和脚手架

开发Vue的两种方式&#xff1a; 1.核心包传统开发模式&#xff1a;基于html/css/js文件&#xff0c;直接引入核心包&#xff0c;开发Vue 2.工程化开发模式&#xff1a;基于构建工具&#xff08;例如&#xff1a;webpack&#xff09;的环境中开发Vue 问题&#xff1a; 1&…

如何安装TortoiseSVN并实现公网提交文件至本地SVN服务器?

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

设计模式16、中介者模式 Mediator

解释说明&#xff1a;中介者模式&#xff08;Mediator Pattern&#xff09;用一个中介对象来封装一系列的对象交互 中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。 抽象中介者&#xff08;Mediator&#xff0…

Kaadas凯迪仕助力亚运盛会,尽展品牌硬核科技与智能锁行业风采

9月23日至10月8日&#xff0c;亚洲最大规模体育赛事亚运会在杭州举办。作为国际性体育赛事&#xff0c;除赛中的各类竞赛项目外&#xff0c;杭州亚运会前后相关活动也吸引了大众目光的聚焦。 Kaadas凯迪仕智能锁作为此次杭州亚运会官方指定智能门锁&#xff0c;以#凯迪仕守护每…

IP真人识别方法与代理IP检测技术

随着互联网的发展&#xff0c;IP地址在网络安全和数据分析中扮演着重要的角色。为了维护网络的安全性和识别真实用户&#xff0c;IP地址的真实性和来源成为了一个关键问题。 什么是IP真人识别&#xff1f; IP真人识别是一种技术&#xff0c;旨在确定IP地址背后的用户是否为真实…

深入理解RBAC

RBAC是一种基于角色实现访问控制的权限管理机制&#xff0c;通过定义角色和权限、用户和角色、角色和角色之间的关系&#xff0c;实现多层次、细粒度、可复用的权限管理系统。原文: Role-based Access Control (RBAC) Model[1] Bernard HermantUnsplash Avery Pennarun写的&quo…

XML文件详解 (java程序解析XML文件,java程序写XML文件)

XML 的全称是可扩展标记语言&#xff08;eXtensible Markup Language&#xff09; xml本质上是一种数据的格式&#xff0c;可以用来存储复杂的数据结构和数据关系。 使用XML&#xff08;可扩展标记语言&#xff09;有以下几个好处&#xff1a; 可读性强&#xff1a;XML使用标…

微信小程序 获取当前屏幕的可见高宽度

很多时候我们做一下逻辑 需要用整个窗口的高度或宽度参与计算 而且很多时候我们js中拿到的单位都是px像素点 没办法和rpx同流合污 官方提供了wx.getSystemInfoSync() 可以获取到部分窗口信息 其中就包括了整个窗口的宽度和高度 wx.getSystemInfoSync().windowHeight 返回值为像…

ElasticSearch 安装,保存,查询,更新,复杂查询,模糊查询,高亮查询

ElasticSearch ik分词器&#xff1a; ik分词器的安装&#xff0c;将ik分词器下载并解压&#xff0c;新建文件夹ik&#xff0c;将解压内容放进ik文件夹中&#xff0c;将ik文件夹放在es安装路径的plugin文件夹中 GET _analyze {"analyzer": "ik_smart",&q…

C++对string进行大小写转换的三种方法

C对string进行大小写转换的三种方法 方法一&#xff1a;下标 #include <iostream> #include <string> using namespace std;int main() {string s "ABCDEFG";for( int i 0; i < s.size(); i ){s[i] tolower(s[i]);}cout<<s<<endl;re…

详细解说iptables 高阶用法,用来完成哪些高效率网络路由策略场景,iptables 实现域名过滤,Linux如何利用iptables屏蔽某些域名?

详细解说iptables 高阶用法,用来完成哪些高效率网络路由策略场景,iptables 实现域名过滤,Linux如何利用iptables屏蔽某些域名? Linux利用iptables屏蔽某些域名 以下规则是屏蔽以 youtube.com 为主的所有一级 二级 三级等域名。 iptables -A OUTPUT -m string --string &qu…

XLSX.utils.sheet_to_json()解析excel,给空的单元格赋值为空字符串

前言 今天用到XLSX来解析excel文件&#xff0c;调用XLSX.utils.sheet_to_json(worksheet)&#xff0c;发现如果单元格为空的话&#xff0c;解析出来的结果&#xff0c;就会缺少相应的key&#xff08;如图所示&#xff09;。但是我想要单元格为空的话&#xff0c;值就默认给空字…

layui tree监控选中事件,同步选中和取消

需求&#xff1a;需要分配权限时&#xff0c;要通过组织架构分配&#xff0c;也要通过角色分配&#xff0c;还是把选择的结果显示出来 结果如下图 代码分页面&#xff0c;类和SQL 页面&#xff1a; <% Page Language"C#" AutoEventWireup"true" Code…

ElasticSearch搜索引擎: 内存分析与设置

在 Elasticsearch 的运行过程中&#xff0c;如何合理分配与设置内存是一件十分重要的事情&#xff0c;否则十分容易出现各种问题。 一、Elasticsearch为什么吃内存&#xff1a; 我们先看下 ES 服务器的总体内存消耗情况&#xff1a; 对于Query Cache、Request Cache、Field…

IT和OT 之间的教育鸿沟

自动化行业正在大力倡导开放自动化系统&#xff0c;使更多IT技术能够导入传统的自动控制行业。并且提出让开放自动化系统消除IT和OT 之间的鸿沟。笔者看来&#xff0c;IT和OT 之间除了技术上的鸿沟之外&#xff0c;还存在着人才鸿沟。近年来&#xff0c;面向智能制造行业的软件…

生物制药公司【Lexeo Therapeutics】申请1亿美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;生物制药公司【Lexeo Therapeutics】近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为(LXEO),Lexeo Therapeutics计划…

万万没想到有一天居然可以在 Mac 上玩游戏,而且还是原神!

万万没想到有一天居然可以在 Mac 上玩游戏&#xff0c;而且还是原神&#xff0c;我真的哭死~ 是这样的&#xff0c;我以前一直用 Mac 来办公也没想过要打游戏&#xff0c;在我心中 Mac 就是用来办公的&#xff0c;生产力工具&#xff0c;直到有一天我刷到一个视频&#xff0c;…

开发餐饮类私域流量是开发应用APP还是小程序还是低代码跨平台APP分析他的利与弊

在开发餐饮类应用程序时&#xff0c;我们需要先了解市场需求&#xff0c;定义目标受众&#xff0c;并提供独特的功能。个人感觉我们提供周围的在线订购、外卖服务、用户评价等功能&#xff0c;以吸引用户。同时&#xff0c;设计用户习惯的界面&#xff0c;使用户轻松选择自己的…

Qt绘图系统

文章目录 一.Qt绘图系统简介二.支持绘图系统的类三.绘图后端四.绘图和填充绘图填充Qt::BrushStyle 五.坐标系系统 一.Qt绘图系统简介 Qt的绘画系统支持使用相同的API在屏幕和打印设备上进行绘画&#xff0c;并且主要基于QPainter、QPaintDevice和QPaintEngine类。这种方法的主…