斐波那契搜索
1、介绍
斐波那契搜索是对二分查找的一种改进,针对的依然是有序序列
2、实现
import java.util.Arrays;
/**
* @author Exticntion
*/
public class FibonacciSearch {
public static int maxSize = 20;
private static int count = 0;
public static void main(String[] args) {
// 创造一个有序数组
int[] sequence = new int[100];
for (int i = 0; i < sequence.length; i++) {
sequence[i] = i + 1;
}
int res = fibonacciSearch(sequence, 98);
System.out.println("查找结果:" + res);
}
/**
* fibonacci search
*
* @param array array
* @param key key
* @return {@link int} 找到就返回数组下标,没有则返回-1
*/
public static int fibonacciSearch(int[] array, int key) {
int low = 0;
int high = array.length - 1;
int mid = 0;
// k 表示斐波那契数列分割数值的下标
int k = 0;
int[] fib = fib();
System.out.println("斐波那契数列如下:");
System.out.println(Arrays.toString(fib));
// 获取斐波那契数列分割的下标,因为要确保斐波那契数列的长度大于等于数组的长度
while (high > fib[k] - 1) {
k++;
}
// 因为 fib[k] 可能大于数组的长度,所以要对数组进行填充,用最后一个值进行填充
// 用 arrays 类复制,不足的部分会用 0 填充
int[] temp = Arrays.copyOf(array, fib[k]);
for (int i = high + 1; i < temp.length; i++) {
temp[i] = array[high];
}
// 使用while循环来处理
while (low <= high) {
count++;
System.out.println("遍历次数~~~" + count);
mid = low + fib[k - 1] - 1;
//我们应该继续向数组的前面查找(左边)
if (key < temp[mid]) {
high = mid - 1;
// 要更新 k 的值
//说明
//1. 全部元素 = 前面的元素 + 后边元素
//2. f[k] = f[k-1] + f[k-2]
//因为前面有 f[k-1] 个元素,所以可以继续拆分 f[k-1] = f[k-2] + f[k-3]
//即在 f[k-1] 的前面继续查找 k--
//即下次循环 mid = f[k-1-1]-1
k--;
// 我们应该继续向数组的后面查找(右边)
} else if (key > temp[mid]) {
low = mid + 1;
//说明
//1. 全部元素 = 前面的元素 + 后边元素
//2. f[k] = f[k-1] + f[k-2]
//3. 因为后面我们有f[k-2] 所以可以继续拆分 f[k-1] = f[k-3] + f[k-4]
//4. 即在f[k-2] 的前面进行查找 k -=2
//5. 即下次循环 mid = f[k - 1 - 2] - 1
k -= 2;
} else {
//还需要确定返回的是哪个下标
if (mid <= high) {
return mid;
} else {
return high;
}
}
}
return -1;
}
/**
* 创建斐波那契数列
* 使用非递归的方式实现斐波那契数列,并返回了斐波那契数组
*/
public static int[] fib() {
int[] sequence = new int[maxSize];
sequence[0] = 1;
sequence[1] = 1;
for (int i = 2; i < maxSize; i++) {
sequence[i] = sequence[i - 1] + sequence[i - 2];
}
return sequence;
}
}