演算法——斐波那契搜尋(查詢)
阿新 • • 發佈:2018-12-10
定義
斐波那契搜尋就是在二分查詢的基礎上根據斐波那契數列進行分割的。在斐波那契數列找一個等於略大於查詢表中元素個數的數F[n],將原查詢表擴充套件為長度為F[n](如果要補充元素,則補充重複最後一個元素,直到滿足F[n]個元素),完成後進行斐波那契分割,即F[n]個元素分割為前半部分F[n-1]個元素,後半部分F[n-2]個元素,找出要查詢的元素在那一部分並遞迴,直到找到。
程式碼實現
import java.util.*; public class FibonacciSearch { /** * <p>name: main</p> * <p>description: </p> * <p>return: void</p> */ public static void main(String[] args) { // TODO Auto-generated method stub int[] array = { 1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68, 88, 88, 88, 88, 88 }; System.out.println("result: " + fbSearch(array, 88)); } /** * <p> * name: fbSearch * </p> * <p> * description: 斐波那契查詢實現 * </p> * <p> * return: int * </p> */ public static int fbSearch(int[] array, int a) { if (array == null || array.length == 0) { return -1; } else { int length = array.length; int[] fb = makeFbArray(20);// 製造一個長度為10的斐波數列 int k = 0; while (length > fb[k] - 1) {// 找出陣列的長度在斐波數列(減1)中的位置,將決定如何拆分 k++; } int[] temp = Arrays.copyOf(array, fb[k] - 1);// 構造一個長度為fb[k] - 1的新數列 for (int i = length; i < temp.length; i++) { if (i >= length) { temp[i] = array[length - 1]; } } int low = 0; int hight = array.length - 1; while (low <= hight) { int middle = low + fb[k - 1] - 1; if (temp[middle] > a) { hight = middle - 1; k = k - 1; } else if (temp[middle] < a) { low = middle + 1; k = k - 2; } else { if (middle <= hight) { return middle;// 若相等則說明mid即為查詢到的位置 } else { return hight;// middle的值已經大於hight,進入擴充套件陣列的填充部分,即最後一個數就是要查詢的數。 } } } return -1; // return recurse(array, fb, a, low, hight, k); } } /** * <p> * name: makeFbArray * </p> * <p> * description: 生成指定長度的斐波數列 * </p> * <p> * return: int[] * </p> */ public static int[] makeFbArray(int length) { int[] array = null; if (length > 2) { array = new int[length]; array[0] = 1; array[1] = 1; for (int i = 2; i < length; i++) { array[i] = array[i - 1] + array[i - 2]; } } return array; } /** * <p> * name: recurse * </p> * <p> * description: 遞迴實現,可以來代替while (low <= hight)遍歷 * </p> * <p> * return: int * </p> */ public static int recurse(int[] array, int[] fb, int a, int low, int hight, int k) { if (array == null || array.length == 0 || a < array[low] || a > array[hight] || low > hight) { return -1; } int middle = low + fb[k - 1] - 1; if (a < array[middle]) { return recurse(array, fb, a, low, middle - 1, k - 1); } else if (a > array[middle]) { return recurse(array, fb, a, middle + 1, hight, k - 2); } else { if (middle <= hight) { return middle; } else { return hight; } } } }