"二分查找(Binary Search)"與"斐波那契查找(Fibonacci Search)"

首先,咱們來看一個筆者的拙做,一段二分查找代碼算法

//返回值是key的下標,若是A中不存在key則返回-1
template <class T>
int BinSearch(T* A, const T &key, int lo, int hi)
{
    int mid;

    while(lo<hi)
    {
        mid = lo + (hi-lo)/2;

        if(key < A[mid])
            hi = mid-1;
        else if(key > A[mid])
            lo = mid+1;
        else
            return mid;

        if(lo==hi && A[lo]==key)
            return lo;
    }
    return -1;
}


    能夠證實,算法的時間複雜度爲O(nlogn),考慮前面的係數的話,大體是O(1.5nlogn)。
數組

    可是,這一實現仍有改進的餘地。注意到循環只須要1次判斷來決定是否轉進到左側,但須要2次判斷來決定是否轉進到右側。也就是進入左、右分支前的關鍵碼比較次數不等。
數據結構

    而斐波那契查找正是優化了這點。利用斐波那契數來對傳入的數組進行黃金分割,這樣前半部分較多然後半部分較少。另外,進入前半部分繼續搜索所需的判斷只有一次,而進入後半部分繼續搜索所需的判斷卻有兩次。如此而來,咱們人爲形成的這種不平衡,反卻是滋長了搜索成本的平衡。
性能

template <class T>
int FibSearch(T* A, const T &key, int lo, int hi)
{
    int mid;
    Fib fib(hi-lo);     //構造一個斐波那契數的類
    while(lo<hi)
    {
        int len = hi-lo;

        while(fib.get()>len)
            fib.prev();     //若是當前的fib.get()返回值大於len,則取前一個斐波那契數
        mid = lo + fib.get() - 1;  //分割節點的下標

        if(key < A[mid])
            hi = mid-1;
        else if(key > A[mid])
            lo = mid+1;
        else
            return mid;

        if(lo==hi && A[lo]==key)
            return lo;
    }
    return -1;
}

    這裏咱們須要構造一個斐波那契數的類。要寫好這個類,其實只須要一個數組,用動態規劃的算法很好寫,這裏再也不贅述。
測試


    既然算法實現好了,咱們就對這兩種算法的正確性作個小測試吧:優化

int main()
{
    a=0,b=0;
    for(int i=0; i<=NUM; ++i)
    {
        A[i] = i;
    }

    for(int i=0; i<=NUM; ++i)   //正確性驗證
    {
        if( BinSearch(A,i,0,NUM) != FibSearch(A,i,0,NUM) )
        {
            cout<<"What a fucking day !" <<i<<endl;
        }
    }
    return 0;
}


    算法性能對比(by fovwin):spa




參考資料:1.清華大學MOOC 《數據結構與算法》 by 鄧俊輝,第二章.net

                 2.Wikipedia - Fibonacci Search Technique (https://en.wikipedia.org/wiki/Fibonacci_search_technique) code

                 3.《"斐波那契查找"真的比二分查找快麼?》 by forwin (強烈推薦,C語言實現,代碼註釋很是清晰 - http://blog.csdn.net/fovwin/article/details/9077017) blog

相關文章
相關標籤/搜索