鋪墊知識:
- 黃金分割點:
黃金分割點是指把一條線段(長度爲H)分割成兩部分A和B,其中A/H=B/A,
取前三位近似值爲0.618,由於按照這個比例設計的造型十分美麗,所以稱作
**黃金分割**,也叫**中外比**。
- 斐波那契數列:
{1,1,2,3,5,8,13,21,34,55...}這個數列滿足如下性質:
1、index爲0和1的元素的值都爲1;
2、從第三個元素開始,都滿足前兩個元素的和等於第三個元素;
3、相鄰兩個元素的比值,無限接近0.618
開始主題:
- 簡單介紹
斐波那契查找算法和二分查找算法和差值查找算法類似,不同之處在於mid
的確定,二分查找算法:
mid = (low + high)/2;//中間值
差值查找算法:
mid = low+(targe-arr[low])*(high-low)/(arr[high]-arr[low])//依據目標值和邊界值的差距而定
斐波那契查找算法:
mid = low+f(k-1)-1//依據斐波那契數列(黃金分割點)
- 具體介紹
斐波那契思想
斐波那契思想與二分法相類似,不過中間點不再是中點,而變成了黃金分割點
的附近mid=low+F(k-1)-1,F代表斐波那契數列
對於F(k-1)-1的含義的理解
1.斐波那契思想與二分法相類似,不過中間點不再是中點,而變成了黃金分割點的附近mid=low+F(k-1)-1,F代表斐波那契數列
對於F(k-1)-1的含義的理解
1.F代表的斐波那契數列
2.k代表斐波那契數列的第k個元素
3.由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-2]-1)兩段,另外一個1就是mid位置的元素
4.類似的每一個子段也可以用同樣的方式來進行分隔
5.但是順序表的長度不一定是恰好等於F[k]-1,所以需要將原來的順序表的長度增加到F[k]-1,這裏的k值僅僅需要恰好使得F[k]-1恰好大於或者等於n,新增位置,都賦值爲下標爲n-1位置的值就可以了
代碼實現
- 代碼:
package Search;
import java.util.Arrays;
import javax.sound.midi.MidiChannel;
public class FbnqSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
FbnqSort fbnqSort = new FbnqSort();
// int[] arr = fbnqSort.fbo();
// System.out.println(Arrays.toString(arr));
int[] arr1 = {1,8,10,89,1000,1200};
int index = fbnqSort.fonqSort(arr1, 1000);
System.out.println(index);
}
//構建斐波那契數列
public int[] fbo() {
int[] fo = new int[20];
fo[0] = 1;
fo[1] = 1;
for (int i = 2; i < fo.length; i++) {
fo[i] = fo[i-1] + fo[i-2];
}
return fo;
}
public int fonqSort(int[] arr, int targe) {
int low = 0;
int high = arr.length-1;
int mid;
int k = 0;//找到f(k)斐波那契數列中的k值
int[] fo = fbo();
//找到比arr數組個數大,且最近的斐波那契數組的k的值
while(arr.length > fo[k]) {
k++;
}
//填充arr數組
int[] temp = Arrays.copyOf(arr, fo[k]);
for(int i = high+1; i < temp.length; i++) {
temp[i] = arr[high];
}
while(low < high) {
mid = low + fo[k-1] - 1;
if(targe > temp[mid]) {//右
low = mid + 1;
k -= 2;
}else if(targe < temp[mid]) {//左
high = mid - 1;
k--;
}else if(mid > high){
return high;
}else {
return mid;
}
}
return -1;
}
}