該博客用於本弱雞複習鞏固,打牢基礎,還望各大佬不吝賜教。java
1import java.util.ArrayList;
2import java.util.Arrays;
3
4/**
5 * Fibonacci Search 斐波那契查找,利用黃金分割原理實現
6 *
7 * 算法複雜度 O(logn)
8 *
9 * 二分查找分割方式 mid = (low+high)/2 加法和除法
10 * 插值查找分割方式 mid = low + (high-low)*(key-a[low])/(a[high]-a[low]) 加減乘除都用上了
11 * 斐波那契查找分割方式 mid = low + Fibonacci[index - 1] - 1
12 *
13 * Fibonacci Search examines relatively closer elements in subsequent steps.
14 * So when input array is big that cannot fit in CPU cache or even in RAM, Fibonacci Search can be useful.
15 */
16public class FibonacciSearch {
17
18 public static void main(String[] args) {
19 int[] a = new int[]{1, 16, 24, 35, 47, 59, 62, 73, 88, 99};
20 System.out.println("待查找數組 a:");
21 System.out.println(Arrays.toString(a));
22 System.out.println();
23 //查找示例1
24 int key = 1;
25 System.out.println("尋找的key爲:" + key);
26 System.out.println("結果在數組 a 角標的 [" + fibonacciSearch(key, a) + "] 位");
27 System.out.println();
28 //查找示例2
29 int key1 = 99;
30 System.out.println("尋找的key爲:" + key1);
31 System.out.println("結果在數組 a 角標的 [" + fibonacciSearch(key1, a) + "] 位");
32 }
33
34 public static int fibonacciSearch(int key, int[] a) {
35 //初始化記錄首位 末位 mid非字面意義上的中間值,僅是將數組分割爲兩部分
36 int low = 0;
37 int high = a.length - 1;
38 int mid;
39 //斐波那契數列中的值-1
40 int fibo = 0;
41 //斐波那契數列中的角標值
42 int index = 0;
43 //用於展現斐波那契數列
44 ArrayList<Integer> fiboArr = new ArrayList<Integer>();
45 //計算length位於斐波那契數列的位置
46 while (a.length > fibo) {
47 fibo = getFibonacci(index) - 1;
48 fiboArr.add(fibo + 1);
49 index++;
50 }
51 //用於展現
52 System.out.println("待查找數組長度爲:" + a.length);
53 System.out.println("斐波那契數列爲:");
54 System.out.println(fiboArr.toString());
55 System.out.println("斐波那契角標 [" + (index - 2) + "] 位爲:" + getFibonacci(index - 2));
56 System.out.println("斐波那契角標 [" + (index - 1) + "] 位爲:" + getFibonacci(index - 1));
57 System.out.println();
58 //-----------------------------
59
60 //要找到在斐波那契數列中大於待查數組長度值的最小值的角標,或者等於待查數組長度值的角標
61 index -= 1;
62 //定義臨時數組來擴展待查數組的長度,長度爲 fibo
63 int[] temp = new int[fibo];
64 for (int i = a.length; i < temp.length; i++) {
65 temp[i] = a[a.length - 1];
66 }
67 for (int i = 0; i < a.length; i++) {
68 temp[i] = a[i];
69 }
70 //展現
71 System.out.println("補充後的數組 temp 爲:");
72 System.out.println(Arrays.toString(temp));
73 System.out.println("補充後的數組長度爲:" + temp.length);
74 //----------------
75
76 //開始查找
77 while (low <= high) {
78 //計算分割數組處的角標
79 mid = low + getFibonacci(index - 1) - 1;
80
81 System.out.println("斐波那契角標 = " + index + " 將key與數組的角標 [" + (mid) + "] 所在的值作比較");
82
83 if (key < temp[mid]) {
84 high = mid - 1;
85 index -= 1;
86 } else if (key > temp[mid]) {
87 low = mid + 1;
88 index -= 2;
89 } else {
90 //若是值相等且角標小於或等於待查數組的最大角標 返回mid 表示找到
91 if (mid <= a.length - 1) {
92 return mid;
93 } else {
94 //若是值相等但角標大於待查數組的最大角標
95 //這樣表示在與temp數組比較時,比較的角標超過了待查數組的角標
96 //但在補充temp數組時,後面的值都是待查數組的最後一位值
97 //因此所尋找的key正好是待查找數組的最後一位
98 System.out.println("所尋找的key正好是待查找數組的最後一位");
99 return a.length - 1;
100 }
101 }
102 }
103 return 0;
104 }
105
106 //生成斐波那契數列
107 public static int getFibonacci(int k) {
108 if (k == 0) {
109 return 0;
110 } else if (k == 1) {
111 return 1;
112 } else if (k > 1) {
113 return getFibonacci(k - 1) + getFibonacci(k - 2);
114 } else {
115 return -1;
116 }
117 }
118}
複製代碼