斐波那契查找(FibonacciSearch)

来源:互联网 发布:大学生如何开淘宝网店 编辑:程序博客网 时间:2024/06/15 15:16
说明
二分搜寻法每次搜寻时,都会将搜寻区间分为一半,所以其搜寻时间为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个费式数:

以10个搜寻对象来说:

Fy = 8, m = 2,所以可以对照费氏数列得到8是第六个费式数,所以y=6,所以x得5,也就是使用第五个费式数的值(也就是5)作为索引开始搜寻。

如果数列在索引5处的值大于指定的搜寻值,则第一个搜寻位置就是索引5的位置,如果小于指定的搜寻值,则第一个搜寻位置必须加上m,也就是F5 + m = 5 + 2 = 7,也就是索引7的位置,其实加上m的原因,是为了要让下一个搜寻值刚好是数列的最后一个位置。

费氏搜寻看来难懂,但只要掌握Fy + m = n这个公式,自己找几个实例算一次,很容易就可以理解;费氏搜寻除了收敛快速之外,由于其本身只会使用到加法与减法,在运算上也可以加快。


C代码

#include <stdio.h> #include <stdlib.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #define INT_MIN -9999void createFibonacci(int[], int);    int findY(int[], int);         int fibonacciSearch(int[], int, int);  int main(void) {    int number[] = {1, 2, 3, 5, 6, 8, 9, 10, 11};int length = sizeof(number) / sizeof(int);printf("数列:"); int i;for(i = 0; i < length; i++) printf("%d ", number[i]); printf("\n输入寻找对象:"); int find;scanf("%d", &find); if((i = fibonacciSearch(number, length, find)) >= 0) printf("找到数字于索引:%d ", i); else printf("\n找不到指定数"); printf("\n"); return 0; } //建立斐波那契数列void createFibonacci(int Fib[], int length) { Fib[0] = 0; Fib[1] = 1; int i;for(i = 2; i < length; i++) Fib[i] = Fib[i-1] + Fib[i-2]; } //找Y值 int findY(int Fib[], int n) { int i = 0; while(Fib[i] <= n) i++; i--; return i; } //斐波那契查找int fibonacciSearch(int number[], int length, int find) { int* Fib = (int*)(malloc(length * sizeof(int)));int f;for(f = 0; f < length; f++) {Fib[f] = INT_MIN;}createFibonacci(Fib, length); int y  = findY(Fib, length + 1); int m = length - Fib[y]; int x = y - 1; int i = x; if(number[i] < find) i += m; int result = -1;while(Fib[x] > 0) { if(number[i] < find) i += Fib[--x]; else if(number[i] > find) i -= Fib[--x]; else {result = i;break;}} free(Fib);return result; }  

转载自:http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/FibonacciSearch.htm



原创粉丝点击