- #include <iostream>
- #include <assert.h>
- #define MAXSIZE 13
- void Fibonacci(int
*f)
- {
- f[0]
= 1;
- f[1]
= 1;
- for (int i
= 2; i
< MAXSIZE; i++)
- {
- f[i]
= f[i
- 1] + f[i
- 2];
- }
- }
- int Fibonacci_Search(int
*a,
int n, int key)
- {
- int low, high,
mid;
- low = 1;
- high = n - 1;
-
- int k = 0;
- int F[MAXSIZE];
- Fibonacci(F);
- //這個查找n在斐波那契數列中的位置,爲什麼是F[k]
- 1,而不是F[k]?
- while ( n
> F[k]
- 1 )
- {
- k++;
- }
- //這個地方,我發現被查找的數組a的長度不好計算,比如,我現在要查找31在數組a中的位置
- //那麼,由於n
= 13, 位於斐波那契數列中的第7個數(21)和第8個數(34)之間,所以k的
- //值爲7,F[k]
- 1就等於20,那麼數組a的長度就需要是a[20]。換個數又變了,我不知道這個
- //應該怎麼控制?
- for (int i
= n; i
< F[k]
- 1; i++)
- {
- a[i]
= a[high];
- }
- //還有這個判斷,當鍵值小於a[mid]時,就在[low,
F[k - 1]
- 1]範圍內查找
- //當鍵值大於a[mid]時,就在[F[k
- 2]
- 1]範圍內查找,這個依據是什麼?
- while(low
<= high)
- {
- mid = low
+ F[k
- 1] - 1;
- if ( key
< a[mid]
)
- {
- high =
mid - 1;
- k = k
- 1;
- }
- else if
( key > a[mid]
)
- {
- low =
mid + 1;
- k = k
- 2;
- }
- else
- {
- if
( mid <= high
)
- {
- return mid;
- }
- else
- return n;
- }
- }
- return -1;
- }
解析:
首先要明確:如果一個有序表的元素個數爲n,並且n正好是(某個斐波那契數 - 1),即n=F[k]-1時,才能用斐波那契查找法。 如果有序表的元素個n不等於(某個斐波那契數 - 1),即n≠F[k]-1,這時必須要將有序表的元素擴展到大於n的那個斐波那契數 - 1才行,這段代碼:
for (int i = n; i < F[k] - 1; i++)
{
a[i] = a[high];
}
便是這個作用。
下面回答
第一個問題:看完上面所述應該知道①是爲什麼了吧。 查找n在斐波那契數列中的位置,爲什麼是F[k] - 1,而不是F[k],是因爲能否用斐波那契查找法是由F[k]-1決定的,而不是F[k]。如果暫時不理解,繼續看下面。
第二個問題:a的長度其實很好估算,比如你定義了有10個元素的有序數組a[10],n=10,那麼n就位於8和13,即F[6]和F[7]之間,所以 k=7,此時數組a的元素個數要被擴充,爲:F[7] - 1 = 12個; 再如你定義了一個b[12],且b有12個元素,即n=12,那麼很好辦了,n = F[7]-1 = 12, 用不着擴充了; 又或者n=8或9或11,則它一定會被擴充到12; 再如你舉的例子,n=13,最後得出n位於13和21,即F[7]和F[8]之間,此時k=8,那麼F[8]-1 = 20,數組a就要有20個元素了。 所以,n = x(13<=x<=20)時,最後都要被擴充到20;類推,如果n=25呢,則數組a的元素個數肯定要被擴充到 34 - 1 = 33個(25位於21和34,即F[8]和F[9]之間,此時k=9,F[9]-1 = 33),所以,n = x(21<=x<=33)時,最後都要被擴充到33。也就是說,最後數組的元素個數一定是(某個斐波那契數 - 1),這就是一開始說的n與F[k]-1的關係。
第三個問題:對於二分查找,分割是從mid= (low+high)/2開始;而對於斐波那契查找,分割是從mid = low + F[k-1] - 1開始的; 通過上面知道了,數組a現在的元素個數爲F[k]-1個,即數組長爲F[k]-1,mid把數組分成了左右兩部分, 左邊的長度爲:F[k-1] - 1, 那麼右邊的長度就爲(數組長-左邊的長度-1), 即:(F[k]-1) - (F[k-1] - 1) = F[k] - F[k-1] - 1 = F[k-2] - 1。
斐波那契查找的核心是:
1)當key=a[mid]時,查找成功;
2)當key<a[mid]時,新的查找範圍是第low個到第mid-1個,此時範圍個數爲F[k-1] - 1個,即數組左邊的長度,所以要在[low, F[k - 1] - 1]範圍內查找;
3)當key>a[mid]時,新的查找範圍是第mid+1個到第high個,此時範圍個數爲F[k-2] - 1個,即數組右邊的長度,所以要在[F[k - 2] - 1]範圍內查找。
附:
上文中不明白之處在於 “如果一個有序表的元素個數爲n,並且n正好是(某個斐波那契數 - 1),即n=F[k]-1時,才能用斐波那契查找法。 如果有序表的元素個n不等於(某個斐波那契數 - 1),即n≠F[k]-1,這時必須要將有序表的元素擴展到大於n的那個斐波那契數 - 1才行”,爲什麼要n=F[k]-1??數學底子比較差,沒法給出數學證明。。。其次就是最後,數組分爲兩部分中左邊長度爲:F[k-1]-1,不知道爲什麼一定要是該值難道F[k-1]不可以嗎??