简体   繁体   English

在斐波那契搜索算法中需要帮助

[英]Need help in fibonacci search algorithm

I am trying to put java code for fibonacci search with my understanding gained from http://en.wikipedia.org/wiki/Fibonacci_search : 我正在尝试通过http://en.wikipedia.org/wiki/Fibonacci_search获得的理解来放入Java代码进行斐波那契搜索:

Let k be defined as an element in F, the array of Fibonacci numbers. 令k定义为F(斐波纳契数)的数组中的元素。 n = Fm is the array size. n = Fm是数组大小。 If the array size is not a Fibonacci number, let Fm be the smallest number in F that is greater than n. 如果数组大小不是斐波那契数,则让Fm为F中大于n的最小数。

The array of Fibonacci numbers is defined where Fk+2 = Fk+1 + Fk, when k ≥ 0, F1 = 1, and F0 = 0. 当k≥0,F1 = 1和F0 = 0时,定义斐波纳契数的数组,其中Fk + 2 = Fk + 1 + Fk。

To test whether an item is in the list of ordered numbers, follow these steps: 要测试某项是否在订购号列表中,请按照下列步骤操作:

Set k = m. 设置k = m。 If k = 0, stop. 如果k = 0,则停止。 There is no match; 没有匹配; the item is not in the array. 该项目不在数组中。 Compare the item against element in Fk−1. 将项目与Fk-1中的元素进行比较。 If the item matches, stop. 如果项目匹配,请停止。 If the item is less than entry Fk−1, discard the elements from positions Fk−1 + 1 to n. 如果该项小于条目Fk-1,则丢弃位置Fk-1 + 1至n中的元素。 Set k = k − 1 and return to step 2. If the item is greater than entry Fk−1, discard the elements from positions 1 to Fk−1. 设置k = k-1并返回到步骤2。如果该项目大于条目Fk-1,则丢弃位置1至Fk-1中的元素。 Renumber the remaining elements from 1 to Fk−2, set k = k − 2, and return to step 2. 将其余元素从1重新编号为Fk-2,设置k = k-2,然后返回步骤2。

The below is my code: 下面是我的代码:

package com.search.demo;

public class FibonacciSearch {

static int[] a = {10,20,30,40,50,60,70,80,90,100};

static int required = 70;
static int m = 2;
static int p = 0;
static int q = 0;


/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    FibonacciSearch fs = new FibonacciSearch();
    fs.findm();
    fibSearch(required);
}

private void findm(){
    //here you have to find Fm which matches size of searching array, or which is close to it.
    int n = a.length;
    int fibCurrent = 1;
    int fibPrev1 = 1;
    int fibPrev2 = 0;

    while(n > fibCurrent){
        fibPrev2 = fibPrev1;
        fibPrev1 = fibCurrent;
        fibCurrent = fibPrev1 + fibPrev2;
        m++;
    }
    p = m-1;
    q = m-2;
}

public static int fibSearch(int no){
    for(;;){

        if(m == 0){
            System.out.println("not found");
            return -1;
        }
        int j = f(p);

        if(no == a[j]){
            System.out.println("found at "+p);
        }else if(no < a[j]){
            m = p;
            p = m - 1;
            q = m - 2;

        }else if(no > a[j]){
            m = q; // as per the step 6..
            p = m-1;
            q = m-2;
        }
    }
    //return m;
}

public static int f(int val){

    if(val == 2 || val == 1 || val == 0){
        return 1;
    }
    return (f(val-1) + f(val-2));
}


}

Please correct me what I am doing wrong, and help me understand it clearly.. 请纠正我在做什么错,并帮助我清楚地理解它。

I have seen this Fibonacci Search and http://www.cs.utsa.edu/~wagner/CS3343/binsearch/searches.html but I am not able to understand.. 我看过这个斐波那契搜索http://www.cs.utsa.edu/~wagner/CS3343/binsearch/searches.html,但我听不懂。

while(n > fibCurrent){
                      fibPrev2 = fibPrev1;
                      fibPrev1 = fibCurrent;
                      fibCurrent = fibPrev1 + fibPrev2;
                      m++;
                    }

This part in the findm() function is actually comparing nth fibonacci number but according to algorithm it should be cumulative sum of the fibonacci numbers upto that point. findm()函数中的该部分实际上是在比较第n个斐波那契数,但根据算法,它应该是直到那个点为止的斐波那契数的累积和。 Rather you can search for the element in while loop of findm. 而是可以在findm的while循环中搜索元素。

Finally I am able to solve the puzzle, that's stopping me.. 终于,我能够解决这个难题,这让我停了下来。

I think the below code should help someone who are stuck as I did. 我认为以下代码应该可以帮助像我一样受困的人。

package com.search.demo;

public class FibonacciSearch {

int a[] = {10,20,30,40,50,60,70,80,90,100};
static FibonacciSearch fs;

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    fs = new FibonacciSearch();
    int location = fs.find(70);
    if(location < 0){
        System.out.println("number not found..");
    }else{
        System.out.println("found at location "+location);
    }
}

private int find(int no){
    int n = a.length;
    int m = findFm(n);                  //m = Fm iff n is Fibonacci number else returns Fm+1
    int p = fibSequenceIterative(m-1);  //p = Fm-1, always a fibonacci number
    int q = fibSequenceIterative(m -2); //q = Fm-2, always a fibonacci number

    while(true){
        if(no == a[m]){
            return m;
        }else if (no < a[m]){
            if(q == 0){
                return -(m - 1);// we crossed 0th index in array, number not found.
            }                   
            m = m - q;  //moved to 1 step left towards a fibonacci num
            int tmp = p;//hold this temporarily
            p = q;      //move p to 1 step left into another fibonacci num
            q = tmp - q;//moved q to 1 step left....
        }else if(no > a[m]){
            if(p == 1){
                return -m;//we reached 0th index in array again and number not found..
            }
            m = m + q;
            p = p - q;
            q = q - p;
        }
    }

}

private int findFm(int n){
    int prev = 1;
    int curr = 1;
    int next = 0;

    if(n == 0){
        next = 0;
        return -1;
    }else if(n == 1 || n == 2){
        next = 1;
        return 1;
    }else{
        for(int i = 3; ; i++){
            next = prev + curr;
            prev = curr;
            curr = next;
            System.out.println("prev = "+prev+" curr = "+curr+" next = "+next);
            if(n <= curr){
                System.out.println("n = "+n+" curr = "+curr);
                return i;
            }
        }
        //return -1;//we should not get here..
    }


}

/* Iterative method for printing Fibonacci sequence..*/
private int fibSequenceIterative(int n){
    int prev = 1;
    int curr = 1;
    int next = 0;

    if(n == 0){
        next = 0;
        //return 0;
    }else if(n == 1 || n == 2){
        next = 1;
        //return 1;
    }else{
        for(int i = 3; i <= n; i++){
            next = prev + curr;
            prev = curr;
            curr = next;
        }
        return next;
    }
    return next;
}


}

The bit of code what I am doing wrong is managing the indexes, which does influence the position of dividing the array at an index postion. 我在做什么错的代码是管理索引,它确实影响在索引位置分割数组的位置。

the m should be find first, to the value that matches n (size of array). 应该首先找到m,直到找到与n(数组大小)匹配的值。 if it doesn't match it should be the next value at which the F(x) will be > nie, in my case size is 10 which doesn't match with any fibonacci number, so the next value in the fibonacci series is 13. and the index of i at which our condition satisfied is F(7) = 13 which is > 10. So m = 7 如果不匹配,则它应该是F(x)> nie的下一个值,在我的情况下,大小是10,它与任何斐波那契数都不匹配,因此斐波那契数列的下一个值是13 ,并且满足我们的条件的i的索引为F(7)= 13,即>10。因此m = 7

and now p and q are 2 consecutive fibonacci numbers which always determine the interval at which to divide the array. 现在p和q是2个连续的斐波那契数,它们始终确定划分数组的间隔。

read the below: 阅读以下内容:

Take N = 54, so that N+1 = 55 = F[10]. 取N = 54,使N + 1 = 55 = F [10]。 We will be searching the sorted array: A[1], ..., A[54], inclusive. 我们将搜索排序后的数组:A [1],...,A [54](含)。 The array indexes are strictly between the two Fibonacci number: 0 < 55. Instead of the midpoint, this search uses the next Fibonacci number down from F[10] = 55, namely F[9] = 34. Instead of dividing the search interval in two, 50% on either side, we divide roughly by the golden ratio, roughly 62% to the left and 38% to the right. 数组索引严格位于两个斐波那契数之间:0 <55。该搜索使用从F [10] = 55向下的下一个斐波那契数,而不是中点,即F [9] =34。而不是划分搜索间隔一分为二,两边各占50%,我们用黄金分割率大致相除,左边约62%,右边约38%。 If y == A[34], then we've found it. 如果y == A [34],那么我们找到了它。 Otherwise we have two smaller intervals to search: 0 to 34 and 34 to 55, not including the endpoints. 否则,我们有两个较小的搜索间隔:0到34和34到55,不包括端点。 If you have two successive Fibonacci numbers, it's easy to march backwards using subtraction, so that above, the next number back from 34 is 55 - 34 = 21. We would break up 0 to 34 with a 21 in the middle. 如果您有两个连续的斐波那契数,则很容易通过减法向后移动,因此在上面,从34返回的下一个数是55-34 =21。我们将中间的21分解为0到34。 The range from 34 to 55 is broken using the next Fibonacci number down: 34 - 21 = 13. The whole interval [34, 55] has length 21, and we go 13 past the start, to 34 + 13 = 47. Notice that this is not a Fibonacci number -- it's the lengths of all the intervals that are.(copied from http://www.cs.utsa.edu/~wagner/CS3343/binsearch/fibsearch.html ) 使用下一个下一个斐波那契数向下破坏从34到55的范围:34-21 =13。整个区间[34,55]的长度为21,我们从起点经过13,直到34 + 13 =47。请注意这不是斐波那契数-而是所有间隔的长度。(从http://www.cs.utsa.edu/~wagner/CS3343/binsearch/fibsearch.html复制)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM