二分查找算法(加法方式:斐波那契查找)

二分查找算法比較熟悉的是折半查找,可是折半查找中計算mid時,有加法和除法。下面介紹僅有加法方式的二分查找算法算法

核心思想利用斐波那契表達式來實現加法方式的折半查找
技巧點:
1)將數組中數的個數(f(n)-1)分紅 f(n-1) -1和 f(n-2)
2):f(n) - 1 = (f(n-1)-1 )+ (f(n-2)-1)
在數組中由於要用到一個mid數(中間位置的數) 故總共要減掉1,故上述表達式成立。數組

  1 #-*-coding: UTF-8 -*-
  2 
  3 
  4 # 
  5 # 時間複雜度O(log(n))
  6  
  7 def fibonacci_search_F1(lis, key):
  8     print("---F1---")
  9     # 須要一個現成的斐波那契列表。其最大元素的值必須超過查找表中元素個數的數值。
 10     F = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,
 11          233, 377, 610, 987, 1597, 2584, 4181, 6765,
 12          10946, 17711, 28657, 46368]
 13     low = 0
 14     high = len(lis) - 1
 15     
 16     # 爲了使得查找表知足斐波那契特性,在表的最後添加幾個一樣的值
 17     # 這個值是原查找表的最後那個元素的值
 18     # 添加的個數由F[k]-1-high決定
 19     k = 0
 20     while high > F[k]-1:
 21         k += 1
 22     print(k)
 23     i = high
 24     while F[k]-1 > i:
 25         lis.append(lis[high])
 26         i += 1
 27     print(lis)
 28     
 29     # 算法主邏輯。time用於展現循環的次數。
 30     time = 0
 31     while low <= high:
 32         time += 1
 33         # 爲了防止F列表下標溢出,設置if和else
 34         if k < 2:
 35             mid = low
 36         else:
 37             #利用F[k-1]來計算中間位置的數
 38             mid = low + F[k-1]-1
 39         
 40         print("low=%s, mid=%s, high=%s" % (low, mid, high))
 41         if key < lis[mid]:
 42             high = mid - 1
 43             k -= 1
 44         elif key > lis[mid]:
 45             low = mid + 1
 46             k -= 2
 47         else:
 48             if mid <= high:
 49                 # 打印查找的次數
 50                 print("times: %s" % time)
 51                 return mid
 52             else:
 53                 print("times: %s" % time)
 54                 return high
 55     print("times: %s" % time)
 56     return False
 57 
 58 def fibonacci_search_F2(lis, key):
 59     print("---F2---")
 60     # 須要一個現成的斐波那契列表。其最大元素的值必須超過查找表中元素個數的數值。
 61     F = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,
 62          233, 377, 610, 987, 1597, 2584, 4181, 6765,
 63          10946, 17711, 28657, 46368]
 64     low = 0
 65     high = len(lis) - 1
 66     
 67     # 爲了使得查找表知足斐波那契特性,在表的最後添加幾個一樣的值
 68     # 這個值是原查找表的最後那個元素的值
 69     # 添加的個數由F[k]-1-high決定
 70     k = 0
 71     while high > F[k]-1:
 72         k += 1
 73     print(k)
 74     i = high
 75     while F[k]-1 > i:
 76         lis.append(lis[high])
 77         i += 1
 78     print(lis)
 79     
 80     # 算法主邏輯。time用於展現循環的次數。
 81     time = 0
 82     while low <= high:
 83         time += 1
 84         # 爲了防止F列表下標溢出,設置if和else
 85         if k < 2:
 86             mid = low
 87         else:
 88             mid = low + F[k-2]-1
 89         
 90         print("low=%s, mid=%s, high=%s" % (low, mid, high))
 91         if key < lis[mid]:
 92             high = mid - 1
 93             k -= 2
 94         elif key > lis[mid]:
 95             low = mid + 1
 96             k -= 1
 97         else:
 98             if mid <= high:
 99                 # 打印查找的次數
100                 print("times: %s" % time)
101                 return mid
102             else:
103                 print("times: %s" % time)
104                 return high
105     print("times: %s" % time)
106     return False
107  
108 if __name__ == '__main__':
109     LIST = [1,2,3,4, 5,6, 7, 8,9,10,11,12,13,14,15,16,17,18,19,20]
110     print("F1:%d" % fibonacci_search_F1(LIST, 15))
111     print("F2:%d" % fibonacci_search_F2(LIST, 15))

以上用兩種方式查找mid的值,主要思想是 mid 既能夠由f(n-1) 得到 又能夠由f(n-2) 得到。app

F1:     f(n-1) + f(n-2) = f(n)spa

F2:     f(n-2) + f(n-1) = f(n)code

相關文章
相關標籤/搜索