对F[k-1]-1的理解:
(1)F[k]=F[k-1]+F[k-2] F[k]-1=(F[k-1]-1)+(F[k-2]-1)+1
说明:只要顺序表长度为F[k]-1,则可以将表分为F[k-1]-1和F[k-1]-1两段,而中间位置为
mid=low+F[k-1]-1
(2)类似的,每个子段也可以用相同放式分割
(3)但顺序表长度n不一定等于F[k]-1,所以需要将原来顺序表长度n增加至F[k]-1,这里K值只要能使F[k]-1恰好大于等于n即可
代码实现:
public class FibonacciSearch {
public static int maxSize=20;
public static void main(String[] args) {
// TODO 自动生成的方法存根
//定义初始数组
int[] arr= {1,8,10,89,1000,1234};
int findVal=10;
System.out.println(fabnacciSearch(arr, findVal));
}
//构建斐波那契数列
public static int[] Fabonacci() {
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;
}
//编写斐波那契查找算法
public static int fabnacciSearch(int[] arr,int findVal) {
int low=0;
int high=arr.length-1;
int k=0; //表示斐波那契分割数值得下标
int mid=0;
int[] f=Fabonacci();
//获取斐波那契分割数值的下标
while(high>f[k]-1) {
k++;
}
//因为f[k]值可能大于数组arr的长度,因此需要使用Arrays类,构造一个新的数组,并指向arr[]
//不足的部分会使用0填充
int[] temp=Arrays.copyOf(arr, f[k]);
//实际上需求使用a数组最后的数填充temp
for(int i=high+1;i<temp.length;i++) {
temp[i]=arr[high];
}
//使用while来循环处理,找到数
while(low<=high) {
mid=low+f[k-1]-1;
if(findVal>temp[mid]) { //向右查找
low=mid+1;
k-=2; //f[k]=f[k-1]+f[k-2] mid左边是f[k-1],右边是f[k-2]
}else if(findVal<temp[mid]) { //向左查找
high=mid-1;
k--;
}else {
if(high>mid) { //因为之前的temp数组填充了arr[high]
return mid;
}else {
return high;
}
}
}
return -1;
}
}