在介紹斐波那契查找算法以前,咱們先介紹一下很它緊密相連而且你們都熟知的一個概念——黃金分割。算法
黃金比例又稱黃金分割,是指事物各部分間必定的數學比例關係,即將總體一分爲二,較大部分與較小部分之比等於總體與較大部分之比,其比值約爲1:0.618或1.618:1。數組
0.618被公認爲最具備審美意義的比例數字,這個數值的做用不單單體如今諸如繪畫、雕塑、音樂、建築等藝術領域,並且在管理、工程設計等方面也有着不可忽視的做用。所以被稱爲黃金分割。spa
你們記不記得斐波那契數列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(從第三個數開始,後邊每個數都是前兩個數的和)。而後咱們會發現,隨着斐波那契數列的遞增,先後兩個數的比值會愈來愈接近0.618,利用這個特性,咱們就能夠將黃金比例運用到查找技術中。設計
也是二分查找的一種提高算法,經過運用黃金比例的概念在數列中選擇查找點進行查找,提升查找效率。一樣地,斐波那契查找也屬於一種有序查找算法。指針
相對於折半查找,通常將待比較的key值與第mid=(low+high)/2位置的元素比較,比較結果分三種狀況:code
[1]相等,mid位置的元素即爲所求blog
[2]>,low=mid+1;遞歸
[3]<,high=mid-1。ci
斐波那契查找與折半查找很類似,他是根據斐波那契序列的特色對有序表進行分割的。他要求開始表中記錄的個數爲某個斐波那契數小1,及n=F(k)-1;數學
開始將k值與第F(k-1)位置的記錄進行比較(及mid=low+F(k-1)-1),比較結果也分爲三種
[1]相等,mid位置的元素即爲所求
[2]>,low=mid+1,k-=2;
說明:low=mid+1說明待查找的元素在[mid+1,high]範圍內,k-=2 說明範圍[mid+1,high]內的元素個數爲n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1個,因此能夠遞歸的應用斐波那契查找。
[3]<,high=mid-1,k-=1。
說明:low=mid+1說明待查找的元素在[low,mid-1]範圍內,k-=1 說明範圍[low,mid-1]內的元素個數爲F(k-1)-1個,因此能夠遞歸 的應用斐波那契查找。
最壞狀況下,時間複雜度爲O(log2n),且其指望複雜度也爲O(log2n)。
public final static int MAXSIZE = 20; /** * 斐波那契數列 * * @return */ public static int[] fibonacci() { int[] f = new int[MAXSIZE]; int i = 0; f[0] = 1; f[1] = 1; for (i = 2; i < MAXSIZE; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; } public static int fibonacciSearch(int[] data, int key) { int low = 0; int high = data.length - 1; int mid = 0; //斐波那契分割數值下標 int k = 0; //序列元素個數 int i = 0; // 獲取斐波那契數列 int[] f = fibonacci(); //獲取斐波那契分割數值下標 while (data.length > f[k] - 1) { k++; } //建立臨時數組 int[] temp = new int[f[k] - 1]; for (int j = 0; j < data.length; j++) { temp[j] = data[j]; } //序列補充至f[k]個元素 //補充的元素值爲最後一個元素的值 for (i = data.length; i < f[k] - 1; i++) { temp[i] = temp[high]; } //打印 for (int j : temp) { System.out.print(j + " "); } System.out.println(); //開始查找 while (low <= high) { // low:起始位置 // 前半部分有f[k-1]個元素,因爲下標從0開始 // 則-1 獲取 黃金分割位置元素的下標 mid = low + f[k - 1] - 1; if (temp[mid] > key) { // 查找前半部分,高位指針移動 high = mid - 1; // (所有元素) = (前半部分)+(後半部分) // f[k] = f[k-1] + f[k-1] // 由於前半部分有f[k-1]個元素,因此 k = k-1 k = k - 1; } else if (temp[mid] < key) { // 查找後半部分,高位指針移動 low = mid + 1; // (所有元素) = (前半部分)+(後半部分) // f[k] = f[k-1] + f[k-1] // 由於後半部分有f[k-1]個元素,因此 k = k-2 k = k - 2; } else { //若是爲真則找到相應的位置 if (mid <= high) { return mid; } else { //出現這種狀況是查找到補充的元素 //而補充的元素與high位置的元素同樣 return high; } } } return -1; } public static void main(String[] args) { int[] f = fibonacci(); for (int i : f) { System.out.print(i + " "); } System.out.println(); int[] data = {1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68, 88}; int search = 39; int position = fibonacciSearch(data, search); System.out.println("值" + search + "的元素位置爲:" + position); }