24、查找算法:斐波那契查找算法

鋪墊知識:

  • 黃金分割點:
黃金分割點是指把一條線段(長度爲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;
		
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章