斐波那契(黄金分割法)原理:
斐波那契查找算法,也同样还是要求待查找序列是有序的
斐波那契查找原理和二分查找、插值查找的原理大致相同,仅仅是改变了中间节点(mid)的位置,mid不再是中间或者插值得到,而是位于黄金分割点附近,即
mid = low + F(k - 1) - 1 //其中F代表的是斐波那契数列
首先需要得到一个斐波那契数列,,再在这个基础上,编写斐波那契查找算法
//斐波那契数列
public static int[] fib() {
int[] f = new int[maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < f.length - 1; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
因为枢轴mid是根据斐波那契F(k - 1)决定的,所以得构造一个长度为 f[k] 的新数组;
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(); //获取斐波那契数列
//获取斐波那契分割数值的下标
while (high > f[k] - 1) {
k++;
}
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;
k--;
}
else if (key > temp[mid]) { //应该继续向数组的后面查找(右边)
low = mid + 1;
k -= 2;
}
else { //找到
//需要确定,返回的是哪个下标
if (mid <= high) {
return mid;
}
else {
return high;
}
}
}
return -1;
}
整个序列的长度是 F[k] - 1,由于需要满足递归,的规律,而且根据斐波那契数列的特点 F[k] = F[k - 1] + F[k - 2],所以就把 mid 的左边分成了 F[k - 1] - 1个数,mid 的右边分成了 F[k - 2] - 1个数,如上图所示,所以在while循环中,往左递归是k–,往右递归是k -= 2;