斐波那契查詢 類似於二分查詢

2021-06-21 13:09:50 字數 2234 閱讀 7459

/*斐波那契查詢法,前提是線性表必須有序,時間複雜度是o(logn)*/

#include

const

intmaxsize = 20;  

intfibonacci_search(

int*a, 

intn, 

intkey);  

/*用非遞迴法構造乙個斐波那契陣列*/

void

fibonacci(

int*f)  

}  intmain()  

;  int

number = fibonacci_search(array, 

sizeof

(array)/

sizeof

(int

), 73);  

std::cout<<"位置是:array["

<"]\n"

;  return

0;  

}  /*定義斐波那契查詢法*/

intfibonacci_search(

int*a, 

intn, 

intkey)  

for(i=n; i//將a的元素擴充套件到(某斐波那契數 - 1),即f[k]-1

while

(low <= high)  

else

if(key > a[mid])  

else

}  return

-1;  

}  

首先要明確:如果乙個有序表的元素個數為n,並且n正好是(某個斐波那契數 - 1),即n=f[k]-1時,才能用斐波那契查詢法。 如果有序表的元素個n不等於(某個斐波那契數 - 1),即n≠f[k]-1,這時必須要將有序表的元素擴充套件到大於n的那個斐波那契數 - 1才行,這段**:

[cpp]

view plain

copy

print?

for(int

i = n; i < f[k] - 1; i++)    

便是這個作用。

陣列a的長度其實很好估算,比如你定義了有10個元素的有序陣列a[20],n=10,那麼n就位於8和13,即f[6]和f[7]之間,所以k=7,此時陣列a的元素個數要被擴充,為:f[7] - 1 = 12個; 再如你定義了乙個b[20],且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)當keya[mid]時,新的查詢範圍是第mid+1個到第high個,此時範圍個數為f[k-2] - 1個,即陣列右邊的長度,所以要在[f[k - 2] - 1]範圍內查詢。

關於斐波那契查詢, 如果要查詢的記錄在右側,則左側的資料都不用再判斷了,不斷反覆進行下去,對處於當眾的大部分資料,其工作效率要高一些。所以儘管斐波那契查詢的時間複雜度也為o(logn),但就平均效能來說,斐波那契查詢要優於折半查詢。可惜如果是最壞的情況,比如這裡key=1,那麼始終都處於左側在查詢,則查詢效率低於折半查詢。

還有關鍵一點,折半查詢是進行加法與除法運算的(mid=(low+high)/2),插值查詢則進行更複雜的四則運算(mid = low + (high - low) * ((key - a[low]) / (a[high] - a[low]))),而斐波那契查詢只進行最簡單的加減法運算(mid = low + f[k-1] - 1),在海量資料的查詢過程中,這種細微的差別可能會影響最終的效率。

二分查詢與斐波那契查詢

方法一 軸點取中點,逐步遞迴。演算法時間複雜度o log n 主要思路如下圖 不會執行 pre 對於該演算法,我們可以計算出迭代到底部所耗費的時間,計算結果如下圖所示。從圖中可以看出左邊遞迴和右邊遞迴所耗費的步數是不一樣的,那我我們是否可以找到一種演算法讓左邊迭代步數和右邊一致能,這樣能夠減少平均迭...

二分查詢,改進 斐波那契查詢

二分查詢 平均查詢長度o 1.5logn 實現 二分查詢演算法 版本a 在有序向量的區間 lo,hi 內查詢元素e,0 lo hi size typdef int rank template typename t static rank binsearch t s,t const e,rank lo...

二分查詢 插值查詢 斐波那契查詢

在有序表中,取中間記錄作為比較物件,將其與給定值相比較,若其等於給定值,則查詢成功 若其小於給定值,則在中間記錄的右半區繼續查詢 若其大於給定值,則在中間記錄的左半區繼續查詢。不斷重複以上過程,直到查詢成功或無匹配記錄。使用該查詢方法的前提條件在於,線性表中的資料必須有序,且必須採用順序儲存的方式。...