有序表查找---斐波那契查找

    注意:斐波那契查找的前提和折半查找和插值查找的条件相同,即待查找的查找表必须是顺序存储且有序。
    斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=f(k)-1。
开始将key值与第f(k-1)位置的记录进行比较(及mid=low+f(k-1)-1),比较结果也分为三种

  • key = a[mid]:mid位置的元素即为所求。
  • key < a[mid]:high=mid-1,k-=1
        high=mid-1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为f(k-1)-1 个,f(k-1)-1是怎么求出来的呢? [low, mid-1]中元素个数为:high-low+1=mid-1-low+1=low+f(k-1)-1-1-low+1=f(k-1)-1。所以可以递归 的应用斐波那契查找。
  • key > a[mid]:low=mid+1,k-=2
        low=mid+1说明待查找的元素在[mid+1,hign]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n - (f(k-1))= f(k)-1-f(k-1)=f(k)-f(k-1)-1f(k-2)-1个,所以可以递归的应用斐波那契查找。
    借鉴图片

n=f(k)-1是为什么?
    是为了格式上的统一,以方便递归或者循环程序的编写。表中的数据是f(k)-1个,使用mid值进行分割又用掉一个,那么剩下f(k)-2个。正好分给两个子序列,每个子序列的个数分别是f(k-1)-1与f(k-2)-1个,格式上与之前是统一的。不然的话,每个子序列的元素个数有可能是f(k-1),f(k-1)-1,f(k-2),f(k-2)-1个,写程序会非常麻烦。

代码如下(Java):

import java.util.Arrays;

public class FibonacciLookup {

	public int max_size = 20;
	public int[] f;
	
	public FibonacciLookup(int max_size) {
		this.max_size = max_size;
		this.f = new int[this.max_size];
	}
	
	public FibonacciLookup() {
		this.f = new int[this.max_size];
	}
	
	public void Fibonacci() {
		this.f[0] = 0;
		this.f[1] = 1;
		for (int i = 2; i < this.max_size; i++) {
			this.f[i] = this.f[i - 1] + this.f[i - 2];
		}
	}
	
	public int Fibonacci_Search(int[] a, int n, int key) {
		int low = 0, high = n - 1, mid;
		int k = 0;
		this.Fibonacci();
		while(n > (this.f[k] - 1)) {
			++k;
		}
		int[] temp = Arrays.copyOf(a, this.f[k] - 1);
		
		for (int i = n; i < temp.length; i++) {
			if(i >= n) {
				temp[i] = temp[n - 1];
			}
		}
		
		while(low <= high) {
			mid = low + this.f[k - 1] - 1;
			if(key < temp[mid]) {
				high = mid - 1;
				k=k-1;
			}
			else if(key > temp[mid]) {
				low = mid + 1;
				k = k-2;
			}
			else {
				if(mid <= high) {
					return mid;
				}
				else {
					return high;
				}
			}
		}
		return -1;
	}

	public static void main(String[] args) {
		int[] a = {1, 16, 24, 35, 47, 59, 62, 73, 88, 99};
		FibonacciLookup f = new FibonacciLookup();
		System.out.println(f.Fibonacci_Search(a, 10, 59));
	}
	
}
posted @ 2019-03-10 22:44  如是说  阅读(219)  评论(0编辑  收藏  举报