斐波那契數列,又稱黃金分割數列,指的是這樣一個數列:一、一、二、三、五、八、1三、2一、····,在數學上,斐波那契被遞歸方法以下定義:F(1)=1,F(2)=1,F(n)=f(n-1)+F(n-2) (n>=2)。該數列越日後相鄰的兩個數的比值越趨向於黃金比例值(0.618)。算法
對於斐波那契數列:一、一、二、三、五、八、1三、2一、3四、5五、89……(也能夠從0開始),先後兩個數字的比值隨着數列的增長,愈來愈接近黃金比值0.618。好比這裏的89,把它想象成整個有序表的元素個數,而89是由前面的兩個斐波那契數34和55相加以後的和,也就是說把元素個數爲89的有序表分紅由前55個數據元素組成的前半段和由後34個數據元素組成的後半段,那麼前半段元素個數和整個有序表長度的比值就接近黃金比值0.618,假如要查找的元素在前半段,那麼繼續按照斐波那契數列來看,55 = 34 + 21,因此繼續把前半段分紅前34個數據元素的前半段和後21個元素的後半段,繼續查找,如此反覆,直到查找成功或失敗,這樣就把斐波那契數列應用到查找算法中了。數組
從圖中能夠看出,當有序表的元素個數不是斐波那契數列中的某個數字時,須要把有序表的元素個數長度補齊,讓它成爲斐波那契數列中的一個數值,固然把原有序表截斷確定是不可能的,否則還怎麼查找。而後圖中標識每次取斐波那契數列中的某個值時(F[k]),都會進行-1操做,這是由於有序表數組位序從0開始的,純粹是爲了迎合位序從0開始。因此用迭代實現斐波那契查找算法以下:spa
1 #include <stdio.h> 2 3 #define FIB_MAXSIZE 100 4 5 /** 6 * 生成斐波那契數列 7 * @param fib:指向存儲斐波那契數列的數組的指針 8 * @param size:斐波那契數列長度 9 */ 10 void ProduceFib(int *fib, int size) 11 { 12 int i; 13 14 fib[0] = 1; 15 fib[1] = 1; 16 17 for (i = 2; i < size; i++) 18 { 19 fib[i] = fib[i - 1] + fib[i - 2]; 20 } 21 } 22 23 /** 24 * 斐波那契查找,查找成功返回位序,不然返回-1 25 * @param data:有序表數組 26 * @param length:有序表元素個數 27 * @param searchValue:待查找關鍵字 28 */ 29 int FibonacciSearch(int *data, int length, int searchValue) 30 { 31 int low, high, mid, k, i, fib[FIB_MAXSIZE]; 32 33 low = 0; 34 high = length - 1; 35 36 ProduceFib(fib, FIB_MAXSIZE); 37 38 k = 0; 39 // 找到有序表元素個數在斐波那契數列中最接近的最大數列值 40 while (high > fib[k] - 1) 41 { 42 k++; 43 } 44 45 // 補齊有序表 46 for (i = length; i <= fib[k] - 1; i++) 47 { 48 data[i] = data[high]; 49 } 50 51 while (low <= high) 52 { 53 mid = low + fib[k - 1] - 1; // 根據斐波那契數列進行黃金分割 54 55 if (data[mid] == searchValue) 56 { 57 if (mid <= length - 1) 58 { 59 return mid; 60 } 61 else 62 { 63 // 說明查找獲得的數據元素是補全值 64 return length - 1; 65 } 66 } 67 68 if (data[mid] > searchValue) 69 { 70 high = mid - 1; 71 k = k - 1; 72 } 73 74 if (data[mid] < searchValue) 75 { 76 low = mid + 1; 77 k = k - 2; 78 } 79 } 80 81 return -1; 82 } 83 84 int main() 85 { 86 int data[] = {1,3,5,7,9,11,13,15,17,19,21}; 87 88 int index = FibonacciSearch(data, 11, 19); 89 printf("%d\n", index); 90 91 return 0; 92 }
斐波那契查找的時間複雜度仍是O(log2n),可是與折半查找相比,斐波那契查找的優勢是它只涉及加法和減法運算,而不用除法,而除法比加減法要佔用更多的時間,所以,斐波那契查找的運行時間理論上比折半查找小,可是仍是得視具體狀況而定指針