思路说明:
斐波那契查找和前三个查找相似,都是需要先定义那个mid比较值,只不过是mid值的定义方式不一样斐波那契算法是让mid保持在数组的黄金分割点处,mid前面长度为F[K-1]-1,后面长度为F[K-2]-1,数组总长度为F[K]-1,mid在黄金分割点。
首先创建一个斐波那契数组
//定义一个斐波那契数列
public static int[] feibo(int l){
int feibArr[]=new int[l];
feibArr[0]=1;
feibArr[1]=1;
for (int i = 2; i <l ; i++) {
feibArr[i]=feibArr[i-1]+feibArr[i-2];
}
return feibArr;
}
然后实现斐波那契方法
//斐波那契查找算法实现
public static int feiboSearch(int arr[],int s){
int fb[]=feibo(arr.length);//获取斐波那契的数组
int left =0;//原始数组左边下标
int right=arr.length-1;//原始数组右边下标
int k=0;//斐波那契数组的下标
while (fb[k]-1<right){//指向数组的最后索引
k++;
}
/* 由于f(k)不是步长为1的递增数列,所以可能出现f(k) - 1的值大于原始数组最后一个索引的情况
比如原始数组最大索引为4,那么此时f(k)就等于5,所以要构造一个新数组,不够的部分会用0填充
如果多余部分用0填充可能会造成查找失败,因此,需要将0的部分填充为原来数组中最后一个数字*/
int temp[]= Arrays.copyOf(arr,fb[k]);
for (int i=right+1;i<temp.length;i++){
temp[i]=arr[right];
}
//开始循环查找
while (left<=right){
int mid=left +fb[k-1]-1;//获取那个离查找值比较近的值
if (s<temp[mid])
{
right=mid-1;
k-=1;
}else if(s>temp[mid]){
left=mid+1;
k-=2;
}else{
return mid<=right? mid:right;//返回下标,这一步当mid的大于right的时候要返回right的值
}
}
//找不到退出循环返回-1
return -1;
}
最后测试和结果图
public static void main(String[] args) {
int arr[]={1,24,55,66,77,88};
int r = feiboSearch(arr, 88);
System.out.println(r);
}
Tips:折半查找是进行加法与除法运算的(mid=(low+high)/2),插值查找则进行更复杂的四则运算(mid = low + (high - low) * ((key - a[low]) / (a[high] - a[low]))),而斐波那契查找只进行最简单的加减法运算(mid = low + F[k-1] - 1),在海量数据的查找过程中,这种细微的差别可能会影响最终的效率。
思路代码感谢大佬小希https://caochenlei.blog.youkuaiyun.com/article/details/114736132