• 费氏搜索浅谈


    说明:

    二分搜尋法每次搜尋時,都會將搜尋區間分為一半,所以其搜尋時間為O(log(2)n),log(2)表示以2為底的log值,

    這邊要介紹的費氏搜尋,其利用費氏數列作為間隔來搜尋下一個數,所以區間收斂的速度更快,搜尋時間為O(logn)。

    解法:

    費氏搜尋使用費氏數列來決定下一個數的搜尋位置,所以必須先製作費氏數列,這在之前有提過;費氏搜尋會先透過公式計算求出第一個要搜尋數的位置,以及其代表的費氏數,以搜尋對象10個數字來說,第一個費氏數經計算後一定是F5,而第一個要搜尋的位置有兩個可能,例如若在下面的數列搜尋的話(為了計算方便,通常會將索引0訂作無限小的數,而數列由索引1開始):

    -∞ 1 3 5 7 9 13 15 17 19 20

    如果要搜尋5的話,則由索引F5F5表示第五個費式數作為索引,也就是5)開始搜尋,接下來如果數列中的數大於指定搜尋值時,就往左找,小於時就向右,每次找的間隔是F4(第四個費式數作為索引,也就是3)、F3(第三個費式數作為索引,也就是2)、F2(第二個費式數作為索引,也就是1)
    來尋找,當費氏數為0時還沒找到,就表示尋找失敗,如下所示:
    費式搜尋

    如果要搜尋19,由於第一個搜尋值索引F5處的值小於19,所以此時必須對齊數列右方,也就是將第一個搜尋值的索引改為F5+2 = 7,然後如同上述的方式進行搜尋,如下所示:
    費式搜尋
    至於第一個搜尋值是如何找到的?我們可以由以下這個公式來求得,其中n為搜尋對象的個數,Fy為第y個費式數,必須大於等於n,若算出x值,則使用Fx作為第一個搜尋索引,也就是第x個費式數:
    Fy + m = n
    Fy
    >= n + 1
    x = y - 1

    以10個搜尋對象來說:
    Fy + m = 10

    Fy = 8, m = 2,所以可以對照費氏數列得到8是第六個費式數,所以y=6,所以x得5,也就是使用第五個費式數的值(也就是5)作為索引開始搜尋。

    如果數列在索引5處的值大於指定的搜尋值,則第一個搜尋位置就是索引5的位置,如果小於指定的搜尋值,則第一個搜尋位置必須加上m,也就是F5 + m = 5 + 2 = 7,也就是索引7的位置,其實加上m的原因,是為了要讓下一個搜尋值剛好是數列的最後一個位置。

    費氏搜尋看來難懂,但只要掌握Fy + m = n這個公式,自己找幾個實例算一次,很容易就可以理解;費氏搜尋除了收斂快速之外,由於其本身只會使用到加法與減法,在運算上也可以加快。


    //建立费氏数列
    void createfib()
    {
          int i;
          Fib[0] = 0;
          Fib[1] = 1;
          for(i = 2; i < MAX;i++)
               Fib[i] = Fib[i-1] + Fib[i-2];
    }

    //找x值
    int findx(int n,int find)
    {
          int i = 0;
          while(Fib[i] <= n)
          i++;
          return --i;
    }
    //费氏搜寻
    int fibsearch(int number[],int find)
    {
            int i ,x,m;
            createfib();
            x = findx(MAX+1,find);
            m = MAX - Fib[x];
            printf("\nx=%d,m = %d,Fib[x] = %d\n\n",x,m,Fib[x]);
            x--;
           i = x;

    //费氏搜索关键代码
          if(number[i] < find)
                 i += m;
          while(Fib[x] > 0)
          {
               if(number[i] < find)
                      i +=Fib[--x];
               else
                    if(number[i] > find)
                           i -= Fib[--x];
                   else
                          return i;
     
            }
           return -1;
    }

  • 相关阅读:
    How to change the property of a control from a flowlayoutpanel?
    Add controls dynamically in flowlayoutpanel
    CLR via C# 读书笔记 6-2 不同AppDomain之间的通信 z
    应用程序域 z
    C# 在SQLite数据库中存储图像 z
    Using .NET 4's Lazy<T> 实现单实例
    tpl demo
    SQLite批量插入,修改数据库 zt
    Dev表格导出工具类 z
    easyui 设置一加载,搜索框立即弹出的效果
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3220874.html
Copyright © 2020-2023  润新知