前边分别介绍了有序表的前两种查找方式二分查找和插值查找,这里再对其另一种方式进行java实现:斐波那契查询。
直接上代码,其中数组扩容和将不满的数值补全是为了防止下标越界异常,当查询的数是有序数组中最后一个值时,在第二个实现查找功能的while循环中的第二次循环时就会发现数组越界,所以这里进行“补偿”。
public class FabnacciSearch {
private static int[] f = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
public static void main(String[] args) {
int[] a = {0, 1, 16, 24, 35, 47, 59, 62, 73, 88, 99};
int result = fibonacciSearch(a, 100);
System.out.println(result);
}
private static int fibonacciSearch(int[] a, int key) {
int low, high, mid, k, n;
n = a.length - 1;
low = 1; // 定义最低下标为记录首位
high = n; // 定义最高下标为记录末位
k = 0;
while (n > f[k] - 1) { // 计算数组长度位于斐波那契数列的位置
k++;
}
/*for (int i = 0; i < f[k] - 1; i++) {// 将不满的数值补全
a[i] = a[n];
}*/
int[] b = new int[f[k] - 1];
System.arraycopy(a, 0, b, 0, a.length);// 数组扩容
a = b;
for (int i = n + 1; i < f[k] - 1; i++) {// 将不满的数值补全
a[i] = a[n];
}
while (low <= high) {
mid = low + f[k - 1] - 1; // 计算当前分隔的下标
if (key < a[mid]) { // 若查找记录小于当前分隔记录
high = mid - 1; // 最高下标调整到分隔下标mid-1处
k = k - 1; // 斐波那契数列下标减一位
} else if (key > a[mid]) { // 若查找记录大于当前分隔记录
low = mid + 1; // 最低下标调整到分隔下标mid+1处
k = k - 2; // 斐波那契数列下标减两位
} else {
if (mid <= n) {
return mid; // 若相等则说明mid即为查找到的位置
} else {
return n; // 若mid>数组长度,说明是补全数值,返回数组长度
}
}
}
return -1;
}
}
这里以重点理解为主。