序言
心若有陽光,你便會看見這個世界有那么多美好值得期待和向往。
決定開一個算法專欄,希望能幫助大家很好的了解算法。主要深入解析每個算法,從概念到示例。
我們一起努力,成為更好的自己!
今天第12講,講一下查找算法的—斐波那契查找
一、算法介紹
斐波那契查找算法是一種基于黃金分割的有序查找算法,通過斐波那契數(shù)列的特性,在有序序列中快速定位目標元素的位置。
1.1 原理介紹
它結(jié)合了二分查找和黃金分割的思想。這個算法的基本原理如下:
序列構(gòu)建: 首先,需要一個有序的數(shù)組或序列。這個數(shù)組的長度通常是斐波那契數(shù)列中的一個值,這有助于在查找過程中對數(shù)組進行分割。
斐波那契數(shù)列: 斐波那契數(shù)列是一組按以下遞歸關系定義的數(shù)字序列:F(0) = 0,F(xiàn)(1) = 1,F(xiàn)(n) = F(n-1) + F(n-2)(n > 1)。通常,斐波那契數(shù)列的前幾項是:0, 1, 1, 2, 3, 5, 8, 13, 21, ...
查找過程: 對于一個有序序列,首先選擇一個斐波那契數(shù)列中的值,使得這個值大于或等于待查找序列的長度,然后使用這個斐波那契數(shù)列的值將序列分成兩個部分。這兩個部分的長度之比就是相鄰兩個斐波那契數(shù)的比例。
比較: 比較要查找的元素與序列中分割點的元素。如果相等,則找到了目標元素;如果待查找元素小于分割點元素,繼續(xù)在前半部分進行查找;如果待查找元素大于分割點元素,繼續(xù)在后半部分進行查找。
迭代: 重復上述步驟,不斷縮小查找范圍,直到找到目標元素或確定元素不在序列中。
示例說明
假設有一個有序數(shù)組
arr
,長度為 n,而 n 正好是斐波那契數(shù)列中的某個值。為了簡化,我們可以選擇 n 為斐波那契數(shù)列中的某個值,比如 F(5) = 5,所以 n = 5。那么,我們有一個有序數(shù)組arr
,長度為 5。
arr = [1, 3, 5, 7, 9]
接下來,我們要查找值為 5 的元素在數(shù)組中的位置。以下是斐波那契查找的步驟:
1.?選擇斐波那契數(shù)列的值: 在斐波那契數(shù)列中找到一個最小的值,使得 F(k) >= n,其中 k 是最小可能滿足的索引。在這個例子中,我們選擇 F(5) = 5。
?2.?分割數(shù)組: 將數(shù)組分成兩個部分,長度比例為斐波那契數(shù)列中的兩個相鄰值的比例。在這個例子中,我們有兩部分,長度比例是 3:2。
? ? ?arr_left = [1, 3, 5]?
arr_right = [7, 9]
3.? 比較與查找: 比較要查找的元素(5)與分割點元素(arr[2] = 5)。如果相等,找到了目標元素。如果待查找元素小于分割點元素,繼續(xù)在前半部分進行查找。如果待查找元素大于分割點元素,繼續(xù)在后半部分進行查找。
?在這個例子中,5 等于分割點元素,所以我們找到了目標元素的位置。
4. 迭代: 重復上述步驟,直到找到目標元素或確定元素不在序列中。
1.2 優(yōu)缺點
優(yōu)點:
適用性廣泛: 斐波那契查找適用于有序序列,尤其在序列長度接近斐波那契數(shù)列的某個值時效果更佳。相較于二分查找,斐波那契查找能夠在某些特定情況下減少查找次數(shù)。
更好的平衡: 由于斐波那契查找使用黃金分割比例進行分割,使得分割后的兩個子序列的長度比例更加接近,有助于保持查找的平衡性。
相對均勻的分割: 斐波那契查找相對于其他分割方法,如二分查找,能夠產(chǎn)生更為均勻的分割,有助于在查找過程中更快地接近目標元素。
缺點:
數(shù)組長度限制: 斐波那契查找要求待查找的序列長度必須是斐波那契數(shù)列中的某個值,這在實際應用中可能不太靈活,特別是當數(shù)據(jù)規(guī)模不是恰好是斐波那契數(shù)列中的某個值時,可能需要對數(shù)據(jù)進行補齊。
比較次數(shù)不穩(wěn)定: 斐波那契查找在某些情況下可能會比二分查找效果更好,但并不是在所有情況下都表現(xiàn)更好。具體的性能取決于待查找數(shù)據(jù)的分布情況和序列的長度。在一些場景下,二分查找可能更為穩(wěn)定。
計算斐波那契數(shù)列: 為了選擇合適的斐波那契數(shù)列的值,需要事先計算斐波那契數(shù)列,這可能涉及到一些計算成本,特別是對于較大的數(shù)據(jù)集。
總體來說,斐波那契查找算法在某些特定條件下表現(xiàn)優(yōu)秀,但在實際應用中需要謹慎選擇,并根據(jù)具體情況考慮使用。在一些情況下,簡單的二分查找可能更加實用和高效。
1.3 復雜度
時間復雜度:
查找過程: 斐波那契查找的主要操作是不斷地縮小查找范圍,通過比較待查找元素與分割點元素來確定繼續(xù)在前半部分還是后半部分進行查找。在每一步操作中,都可以將待查找范圍縮小為原來的黃金分割比例,即約為 0.618。
時間復雜度: 斐波那契查找的時間復雜度可以表示為 O(log n),其中 n 是待查找序列的長度。與二分查找相比,它的復雜度相對更低。
空間復雜度:
常數(shù)空間: 斐波那契查找算法的空間復雜度非常低。它只需要常數(shù)級別的額外空間來存儲一些中間變量,如斐波那契數(shù)列的值、分割點等。
O(1): 因此,斐波那契查找的空間復雜度可以表示為 O(1)。
總體來說,斐波那契查找在時間復雜度和空間復雜度上都相對較低,這使得它在某些特定場景下成為一個有效的查找算法。
但需要注意,實際效果還受到數(shù)據(jù)分布等因素的影響,因此在選擇查找算法時,需要綜合考慮具體情況。
1.4 使用場景
斐波那契查找算法在一些特定的場景下表現(xiàn)良好,適用于如下情況:
有序序列: 斐波那契查找要求待查找的序列是有序的,因為它是基于比較來縮小查找范圍的。如果序列無序,需要先進行排序操作。
長度接近斐波那契數(shù): 算法對序列的長度有一定的要求,最好是恰好是斐波那契數(shù)列中的某個值。在實際應用中,可以選擇最接近并大于待查找序列長度的斐波那契數(shù)。
分布均勻: 如果數(shù)據(jù)在序列中的分布相對均勻,斐波那契查找可以更好地發(fā)揮其優(yōu)勢。這是因為它能夠在分割序列時保持更好的平衡。
查找頻繁但數(shù)據(jù)變動不頻繁: 如果對同一序列進行多次查找而且序列基本保持不變,斐波那契查找的一些前期計算可以提前完成,然后多次使用相同的計算結(jié)果進行查找,從而提高效率。
適用于內(nèi)存有限的情況: 斐波那契查找只需要常數(shù)級別的額外空間,因此在內(nèi)存有限的情況下比一些其他算法更為適用。
需要注意的是,斐波那契查找并不總是比其他查找算法更好,它在特定的條件下才會表現(xiàn)出色。在實際應用中,需要根據(jù)具體情況選擇最適合的查找算法。
二、代碼實現(xiàn)
2.1 Java代碼實現(xiàn)
2.1.1 代碼示例
public class FibonacciSearch {
// 輔助函數(shù):生成斐波那契數(shù)列
private static int[] generateFibonacci(int n) {
int[] fibonacci = new int[n];
fibonacci[0] = 0;
fibonacci[1] = 1;
for (int i = 2; i < n; i++) {
fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
}
return fibonacci;
}
// 斐波那契查找算法
public static int fibonacciSearch(int[] arr, int key) {
int n = arr.length;
// 生成斐波那契數(shù)列,找到最接近且大于等于 n 的值
int[] fibonacci = generateFibonacci(n);
int k = 0;
while (fibonacci[k] < n) {
k++;
}
// 將數(shù)組擴展到斐波那契數(shù)列的長度
int[] temp = new int[fibonacci[k]];
System.arraycopy(arr, 0, temp, 0, n);
int low = 0;
int high = n - 1;
// 主要查找過程
while (low <= high) {
int mid = low + fibonacci[k - 1] - 1;
if (key < temp[mid]) {
high = mid - 1;
k -= 1;
} else if (key > temp[mid]) {
low = mid + 1;
k -= 2;
} else {
// 找到了目標元素,需要判斷返回的是原數(shù)組中的索引還是擴展數(shù)組中的索引
return Math.min(mid, high);
}
}
// 未找到目標元素
return -1;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9, 11, 13, 15};
int key = 7;
int result = fibonacciSearch(arr, key);
if (result != -1) {
System.out.println("元素 " + key + " 在數(shù)組中的索引為:" + result);
} else {
System.out.println("元素 " + key + " 不在數(shù)組中");
}
}
}
2.1.2 代碼詳解
generateFibonacci
方法:生成斐波那契數(shù)列,參數(shù)n
表示生成數(shù)列的長度。
fibonacciSearch
方法:實現(xiàn)了斐波那契查找算法。首先,通過調(diào)用generateFibonacci
方法生成斐波那契數(shù)列,然后找到最接近并大于等于數(shù)組長度的斐波那契數(shù)。接著,將原數(shù)組擴展到斐波那契數(shù)列的長度,再進行主要的查找過程。查找過程中,根據(jù)比較的結(jié)果不斷縮小查找范圍,直到找到目標元素或確定元素不在序列中。
main
方法:在這里,創(chuàng)建一個有序數(shù)組arr
,并調(diào)用fibonacciSearch
方法查找元素 7 的索引。最后,輸出查找結(jié)果。
2.1.3 運行結(jié)果
元素 7 在數(shù)組中的索引為:3
2.2 Python代碼實現(xiàn)
2.2.1 代碼示例
def generate_fibonacci(n):
"""生成斐波那契數(shù)列"""
fibonacci = [0, 1]
while fibonacci[-1] < n:
fibonacci.append(fibonacci[-1] + fibonacci[-2])
return fibonacci
def fibonacci_search(arr, key):
"""斐波那契查找算法"""
n = len(arr)
# 生成斐波那契數(shù)列,找到最接近且大于等于 n 的值
fibonacci = generate_fibonacci(n)
k = 0
while fibonacci[k] < n:
k += 1
# 將數(shù)組擴展到斐波那契數(shù)列的長度
temp = arr + [arr[-1]] * (fibonacci[k] - n)
low, high = 0, n - 1
# 主要查找過程
while low <= high:
mid = low + fibonacci[k - 1] - 1
if key < temp[mid]:
high = mid - 1
k -= 1
elif key > temp[mid]:
low = mid + 1
k -= 2
else:
# 找到了目標元素,返回原數(shù)組中的索引
return min(mid, n - 1)
# 未找到目標元素
return -1
if __name__ == '__main__':
# 測試
arr = [1, 3, 5, 7, 9, 11, 13, 15]
key = 7
result = fibonacci_search(arr, key)
if result != -1:
print(f"元素 {key} 在數(shù)組中的索引為:{result}")
else:
print(f"元素 {key} 不在數(shù)組中")
2.2.2 代碼詳解
generate_fibonacci
函數(shù):用于生成斐波那契數(shù)列,直到數(shù)列的最后一個值大于等于給定的參數(shù)n
。
fibonacci_search
函數(shù):實現(xiàn)了斐波那契查找算法。首先,調(diào)用generate_fibonacci
函數(shù)生成斐波那契數(shù)列,然后找到最接近并大于等于數(shù)組長度的斐波那契數(shù)。接著,將原數(shù)組擴展到斐波那契數(shù)列的長度,再進行主要的查找過程。查找過程中,根據(jù)比較的結(jié)果不斷縮小查找范圍,直到找到目標元素或確定元素不在序列中。
在測試部分,創(chuàng)建一個有序數(shù)組 arr
,并調(diào)用 fibonacci_search
函數(shù)查找元素 7 的索引。最后,輸出查找結(jié)果。
2.2.3 運行結(jié)果
元素 7 在數(shù)組中的索引為:3
好啦,今天就到這里啦,下期見嘍~~??
三、圖書推薦
3.1 圖書名稱
圖書名稱:《Pandas數(shù)據(jù)分析》
Pandas是強大且流行的庫,是Python中數(shù)據(jù)科學的代名詞。這本書會介紹如何使用Pandas對真實世界的數(shù)據(jù)集進行數(shù)據(jù)分析,如股市數(shù)據(jù)、模擬黑客攻擊的數(shù)據(jù)、天氣趨勢、地震數(shù)據(jù)、葡萄酒數(shù)據(jù)和天文數(shù)據(jù)等。
Pandas使我們能夠有效地處理表格數(shù)據(jù),從而使數(shù)據(jù)整理和可視化變得更容易。等不及的小伙伴,可以點擊這個鏈接先睹為快?《Pandas數(shù)據(jù)分析》
3.2 圖書介紹?
3.3 參與方式
圖書數(shù)量:本次送出 2?本 ? !??!??????
活動時間:截止到 2024-01-09?12:00:00抽獎方式:
- 評論區(qū)隨機抽取小伙伴!
留言內(nèi)容,以下方式都可以:
- 根據(jù)文章內(nèi)容進行高質(zhì)量評論
參與方式:關注博主、點贊、收藏,評論區(qū)留言?
3.4 中獎名單
???? 獲獎名單????
?中獎名單:請關注博主動態(tài)文章來源:http://www.zghlxwxcb.cn/news/detail-778629.html
名單公布時間:2024-01-09?下午文章來源地址http://www.zghlxwxcb.cn/news/detail-778629.html
到了這里,關于【算法系列 | 12】深入解析查找算法之—斐波那契查找的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!