算法 - 查找 - 斐波那契查找 (Fibonacci Search)
返回上级:算法 - 查找与排序 (Searching and Sorting)
本文将用C++实现通用模板斐波那契查找算法,复制代码直接可使用。
在查看本文之前,需要一些程序语言的基础。
还需要熟悉 算法 - 查找 - 二分查找 (Binary Search) 。
文章目录
1 斐波那契查找简述 (Introduction)
斐波那契查找,是二分查找的一个变种。其时间复杂度 O(log2n) 。
斐波那契数列,又称黄金分割数列, F = { 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , . . . } F = \{ 1, 1, 2, 3, 5, 8, 13, 21, 34, ... \} F={ 1,1,2,3,5,8,13,21,34,...} 数学表达式:
F 0 = 1 F 1 = 1 F 2 = F 0 + F 1 ⋮ F i = F i − 2 + F i − 1 ( i ≥ 2 ) \begin{aligned} F_0 &= 1 \\ F_1 &= 1 \\ F_2 &= F_0 + F_1 \\ & \vdots \\ F_i &= F_{i-2} + F_{i-1} \quad (i \geq 2) \end{aligned} F0F1F2Fi=1=1=F0+F1⋮=Fi−2+Fi−1(i≥2)
之所以它又称为黄金分割数列,是因为它的前一项与后一项的比值随着数字数量的增多逐渐逼近黄金分割比值0.618。
所以斐波那契查找改变了二分查找中原有的中值 mid 的求解方式,其 mid 不再代表中值,而是代表了黄金分割点:
m i d = l e f t + F b l o c k − 1 − 1 mid = left + F_{block - 1} - 1 mid=left+Fblock−1−1
-
二分查找,以一半元素来分割数组;
-
斐波那契查找,以黄金分割点来分割数组。
假设表中有 n 个元素,查找过程为取区间中间元素的下标 mid ,对 mid 的关键字与给定值的关键字比较:
-
(1)如果与给定关键字相同,则查找成功,返回在表中的位置;
-
(2)如果给定关键字大,向右查找并减小2个斐波那契区间;
-
(3)如果给定关键字小,向左查找并减小1个斐波那契区间;
-
(4)重复过程,直到找到关键字(成功)或区间为空集(失败)。
通常情况下:
-
返回值,代表下标;
-
返回-1,代表没有找到关键字;
举例,假设有集合 e0=2, e1=3, e2=7, e3=14, e4=22, e5=33, e6=55, e7=75, e8=89, e9=123 。
查找元素44
的过程:
-
已知:
- 元素数量
size = 10
; - 下标区间 [low, high] 为
left = 0
、right = 9
。
- 元素数量
-
则初始化的斐波那契数列为 F i b = { 1 , 1 , 2 , 3 , 5 , 8 , 13 } Fib = \{ 1, 1, 2, 3, 5, 8, 13 \} Fib={ 1,1,2,3,5,8,13} ,即斐波那契数列最后一位要比
size - 1
大。 -
此时查找第一步为:此时刚初始化完,斐波那契数列最后一个区间为第6个区间,即区间(8, 13);第8个数字为当前黄金分割点,则第8个数字下标为下标
7
,检测的数字为 e7 ;以8分割数组后,左区间为(1, 8)。b l o c k 0 = 6 m i d 0 = l e f t 0 + F i b [ b l o c k 0 − 1 ] − 1 = 0 + 8 − 1 = 7 i n d e x 0 = min ( m i d 0 , s i z e − 1 ) = 7 ∵ ( e = 44 ) < ( E [ i n d e x 0 ] = 75 ) (小于,去左区间) ∴ l e f t 1 = l e f t 0 = 0 r i g h t 1 = m i d 0 − 1 = 6 b l o c k 1 = b l o c k 0 − 1 = 5 \begin{array}{rl} block_0 &= 6 \\ mid_0 &= le