import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import java.util.Arrays;
public class E1_4_22 {
public static void main(String[]args){
//测试程序
int[]a={0,1,2,4,5,6,7};
StdOut.println(FibonacciBinSearch(a,2));
StdOut.println(FibonacciBinSearch(a,7));
//Doubling Ratio test
int N=125;
double prev=timeTrial(N);
for (N=250;true;N+=N){
double now=timeTrial(N);
StdOut.printf("N=%10d time=%7.6f ratio=%6.5f\n",N,now,now/prev);
prev=now;
}
}
public static double timeTrial(int N){
int MAX=1000000;
int[]a=new int[N];
for (int i=0;i<N;i++)
a[i]= StdRandom.uniform(-MAX, MAX);
Arrays.sort(a);
StopWatch time=new StopWatch();
int index=FibonacciBinSearch(a,StdRandom.uniform(-MAX,MAX));
return time.elapsedTime();
}
public static int FibonacciBinSearch(int[]a,int key){
//a已经增序排列
int f1=1,f2=1;
while (f2<a.length){//找到略大于a.length的第一个Fibonacci数
int temp=f1+f2;
f1=f2;
f2=temp;
}
int lo=0;
int hi=a.length-1;
while (lo<hi&&f1>0){
int mid=lo+f2-f1;
if ((mid==0&&a[mid]>key)||(mid==a.length-1&&a[mid]<key))
return -1;
if (a[mid]>key){
hi=lo+f2-f1;//hi=i+F(k-2)
//update F(k-2)=Fk
f2=f2-f1;
f1=f1-f2;
}
else if (a[mid]<key){
hi=Math.min(hi,lo+f2);
lo+=f2-f1;
//update F(k-1)=Fk
int temp=f2-f1;
f2=f1;
f1=temp;
}
else
return mid;
}
return -1;
}
}