斐波那契查找
个人理解
一个很神奇的算法
前提:有序序列
之前我们的二分查找法,是和中间值比较的。那?
可不可以比较个别的呢?
比如,性感的黄金比例分割点?
正好研究数学的那群人又研究了个很神奇的数列
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765…]
它有这样的规律: F(k)=F(k-1)+F(k-2)
然后相邻的两个呢,又是基本符合黄金比例的(怎么样,惊不惊喜,我也不明白咋回事)
这么着就找到个相应的黄金比例分割点了
然后就是比较了,和以前一样,关键值小于比较值,最大的索引变到关键值对应的左边继续找。大于的话最小值变化到右边。
唯一有点意思的在于找黄金比例分割点
如果关键值在左边的话,无非就是往前面倒腾到上一个黄金比例分割点。右边的话,需要把握一下 F(k)=F(k-1)+F(k-2)这个小技巧了。
说明F(k)-F(k-1)=F(k-2),两个差的黄金比例分割点的值=最小值+等于往前倒腾两个的值
具体的过程不详细阐述,都在代码里了
代码实现之
package search;
import java.util.Arrays;
public class FibonacciSearch
{
static int maxsize = 20;
static int[] fib = new int[maxsize];
// 斐波那契查找
public static void main(String[] args)
{
int[] arr =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
int index = fibSearch(arr, 10);
System.out.println(index);
}
public static void fib()
{
fib[0] = 1;
fib[1] = 1;
for (int i = 2; i < maxsize; i++)
{
fib[i] = fib[i - 1] + fib[i - 2];
}
// System.out.println(Arrays.toString(fib));
// System.out.println("--------------------");
}
public static int fibSearch(int[] arr, int key)
{
int k = 0;
int low = 0;
int high = arr.length - 1;
int mid = 0;
fib();
while (high > fib[k] - 1)
{
k++;
}
// 复制数组到f[k]长度
int[] temp = Arrays.copyOf(arr, fib[k]);
for (int i = high + 1; i < temp.length; i++)
{
temp[i] = arr[high];
}
int index = -1;
while (low <= high)
{
mid = low + fib[k - 1] - 1;
if (key < temp[mid])
{
high = mid - 1;
// 黄金分割点变换到左边
k--;
} else if (key > temp[mid])
{
low = mid + 1;
// 黄金分割点变换到右边
k -= 2;
} else
{
// 找到了,看是不是补全值
if (mid <= temp.length - 1)
{
index = mid;
return index;
} else
{
index = temp.length - 1;
return index;
}
}
}
return index;
}
}