斐波那契查找算法(黃金分割查找算法)
什么是斐波那契查找
斐波那契數(shù)列,又稱黃金分割數(shù)列,指的是這樣一個(gè)數(shù)列:1、1、2、3、5、8、13、21、····,在數(shù)學(xué)上,斐波那契被遞歸方法如下定義:F(1)=1,F(xiàn)(2)=1,F(xiàn)(n)=f(n-1)+F(n-2) (n>=2)。該數(shù)列越往后相鄰的兩個(gè)數(shù)的比值越趨向于黃金比例值(0.618)。
對(duì)于斐波那契數(shù)列:1、1、2、3、5、8、13、21、34、55、89……(也可以從0開始),前后兩個(gè)數(shù)字的比值隨著數(shù)列的增加,越來越接近黃金比值0.618。比如這里的89,把它想象成整個(gè)有序表的元素個(gè)數(shù),而89是由前面的兩個(gè)斐波那契數(shù)34和55相加之后的和,也就是說把元素個(gè)數(shù)為89的有序表分成由前55個(gè)數(shù)據(jù)元素組成的前半段和由后34個(gè)數(shù)據(jù)元素組成的后半段,那么前半段元素個(gè)數(shù)和整個(gè)有序表長(zhǎng)度的比值就接近黃金比值0.618,假如要查找的元素在前半段,那么繼續(xù)按照斐波那契數(shù)列來看,55 = 34 + 21,所以繼續(xù)把前半段分成前34個(gè)數(shù)據(jù)元素的前半段和后21個(gè)元素的后半段,繼續(xù)查找,如此反復(fù),直到查找成功或失敗,這樣就把斐波那契數(shù)列應(yīng)用到查找算法中了。

從圖中可以看出,當(dāng)有序表的元素個(gè)數(shù)不是斐波那契數(shù)列中的某個(gè)數(shù)字時(shí),需要把有序表的元素個(gè)數(shù)長(zhǎng)度補(bǔ)齊,讓它成為斐波那契數(shù)列中的一個(gè)數(shù)值,當(dāng)然把原有序表截?cái)嗫隙ㄊ遣豢赡艿模蝗贿€怎么查找。然后圖中標(biāo)識(shí)每次取斐波那契數(shù)列中的某個(gè)值時(shí)(F[k]),都會(huì)進(jìn)行-1操作,這是因?yàn)橛行虮頂?shù)組位序從0開始的,純粹是為了迎合位序從0開始。所以用迭代實(shí)現(xiàn)斐波那契查找算法如下:
1 #include <stdio.h> 2 3 #define FIB_MAXSIZE 100 4 5 /** 6 * 生成斐波那契數(shù)列 7 * @param fib:指向存儲(chǔ)斐波那契數(shù)列的數(shù)組的指針 8 * @param size:斐波那契數(shù)列長(zhǎng)度 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:有序表數(shù)組 26 * @param length:有序表元素個(gè)數(shù) 27 * @param searchValue:待查找關(guān)鍵字 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 // 找到有序表元素個(gè)數(shù)在斐波那契數(shù)列中最接近的最大數(shù)列值 40 while (high > fib[k] - 1) 41 { 42 k++; 43 } 44 45 // 補(bǔ)齊有序表 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; // 根據(jù)斐波那契數(shù)列進(jìn)行黃金分割 54 55 if (data[mid] == searchValue) 56 { 57 if (mid <= length - 1) 58 { 59 return mid; 60 } 61 else 62 { 63 // 說明查找得到的數(shù)據(jù)元素是補(bǔ)全值 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 }
斐波那契查找的時(shí)間復(fù)雜度還是O(log2n),但是與折半查找相比,斐波那契查找的優(yōu)點(diǎn)是它只涉及加法和減法運(yùn)算,而不用除法,而除法比加減法要占用更多的時(shí)間,因此,斐波那契查找的運(yùn)行時(shí)間理論上比折半查找小,但是還是得視具體情況而定

浙公網(wǎng)安備 33010602011771號(hào)