斐波那契查找(黄金分割法)
-
基本介绍:
- 黄金分割点是指把一条线段分割成两部分,使其中一部分与全长之比等于另一部分与这部分之比
- 斐波那契数列{1, 1, 2, 3, 5, 8, 13, 21, 34, 55}:前两个数为1,后面的数是前面两个数的和。
- 发现斐波那契数列的两个相邻数的比例,无限接近黄金分隔值0.618,比如21/34,34/55,十分接近0.618.
-
查找原理
原理与前两种(二分、插值)相似,**仅仅只是改变了中间节点mid的位置,**mid不是中间或者插入得到,二十位于黄金分割点附近,即mid = left+F(k-1)-1 (F代表斐波那契数列)
对F(k-1)-1的理解
-
代码实现——
请对一个有序数组进行斐波那契查找{1,8,10,89,1000,1234},输入值,输出下标;
package DataStructures.Search; import java.util.Arrays; public class FibonacciSearch { public static int maxSize = 20; public static void main(String[] args) { int arr[] = {1, 8, 10, 89, 1000, 1234}; System.out.println(fibSearch(arr,8)); } //获取斐波那契数列,才能mid = low+F(k-1)-1 //非递归方法得到斐波那契数列 public static int[] fib() { int f[] = new int[maxSize]; f[0] = 1; f[1] = 1; for (int i = 2; i < maxSize; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; } //编写斐波那契查找算法 /** * 非递归的方式 * * @param a 数组 * @param key 需要查找的关键码 * @return 返回对应下表,没有就返回-1 */ public static int fibSearch(int a[], int key) { int low = 0; int high = a.length - 1; int k = 0;//表示斐波那契分割数值的下标 int mid = 0; int f[] = fib(); //获取到k while (high > f[k] - 1) { k++; } //因为f[k]值可能大于数组的长度,因此我们需要使用Arrays类, //构造一个新的数组,并指向temp[] //不足的部分会使用0填充 int temp[] = Arrays.copyOf(a, f[k]); //实际上需要使用a数组最后的数填充temp for (int i = high + 1; i < temp.length; i++) { temp[i] = a[high]; } //使用while循环来循环处理,找到我们的数key while (low <= high) { mid = low + f[k - 1] - 1; if(key<temp[mid]){ //说明我们应该向左查找 high = mid-1; /** * 说明 * 全部元素=前面的元素+后面的元素 * f[k] = f[k-1]+f[k-2] * 因为前面有f[k-1]个元素,所以我们可以继续拆分 * f[k-1] = f[k-2]+f[k-3] * 即在f[k-1]的前面继续查找,k-- */ k--; }else if (key>temp[mid]){ //说明我们应该向右查找 low = mid+1; /** * 说明 * 全部元素=前面的元素+后面的元素 * f[k] = f[k-1]+f[k-2] * 因为后面还有f[k-2]个元素,所以可以继续拆分 * f[k-2] = f[k-3]+f[k-4] * 即在f[k-2]的前面可以继续进行查找 * 即下次循环,mid = f[k-1-2]-1 */ k -=2; }else { //找到 //需要确定,返回的是哪个下标 if (mid<=high){ return mid; }else { return high; } } } return -1; } }