首先,咱們來看一個筆者的拙做,一段二分查找代碼算法
//返回值是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