斐波那契查找详解

    斐波那契查找的前提是待查找的查找表必须顺序存储并且有序。

    相对于折半查找,一般将待比较的key值与第mid=(low+high)/2位置的元素比较,比较结果分三种情况

     1)相等,mid位置的元素即为所求

     2)>     ,low=mid+1;

     3)  <     ,high=mid-1;

   斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=Fk-1;

 开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种

 1)相等,mid位置的元素即为所求

 2)>   ,low=mid+1,k-=2;

说明:low=mid+1说明待查找的元素在[mid+1,hign]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找

 3)<    ,high=mid-1,k-=1;

说明:low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1

个,所以可以递归 的应用斐波那契查找


斐波那契查找的算法如下:

// 斐波那契查找.cpp 

#include "stdafx.h"
#include 
#include  
using namespace std;

const int max_size=20;//斐波那契数组的长度

/*构造一个斐波那契数组*/ 
void Fibonacci(int * F)
{
	F[0]=0;
	F[1]=1;
	for(int i=2;iF[k]-1)//计算n位于斐波那契数列的位置
	  ++k;

  int  * temp;//将数组a扩展到F[k]-1的长度
  temp=new int [F[k]-1];
  memcpy(temp,a,n*sizeof(int));

  for(int i=n;itemp[mid])
	{
     low=mid+1;
	 k-=2;
	}
	else
	{
       if(mid=n则说明是扩展的数值,返回n-1
	}
  }  
  delete [] temp;
  return -1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = {0,16,24,35,47,59,62,73,88,99};
	int key=100;
	int index=Fibonacci_Search(a,sizeof(a)/sizeof(int),key);
	cout<

斐波那契查找的核心是:
1)当key=a[mid]时,查找成功;
2)当key 3)当key>a[mid]时,新的查找范围是第mid+1个到第high个,此时范围个数为F[k-2] - 1个,即数组右边的长度,所以要在[F[k - 2] - 1]范围内查找。

 

   关于斐波那契查找, 如果要查找的记录在右侧,则左侧的数据都不用再判断了,不断反复进行下去,对处于当众的大部分数据,其工作效率要高一些。所以尽管斐波那契查找的时间复杂度也为O(logn),但就平均性能来说,斐波那契查找要优于折半查找。可惜如果是最坏的情况,比如这里key=1,那么始终都处于左侧在查找,则查找效率低于折半查找。

   还有关键一点,折半查找是进行加法与除法运算的(mid=(low+high)/2),插值查找则进行更复杂的四则运算(mid = low + (high - low) * ((key - a[low]) / (a[high] - a[low]))),而斐波那契查找只进行最简单的加减法运算(mid = low + F[k-1] - 1),在海量数据的查找过程中,这种细微的差别可能会影响最终的效率。


参考文献:严蔚敏数据结构c语言版 221页 及芦苇csdn博客  http://blog.csdn.net/zpluw/article/details/7757331



你可能感兴趣的:(算法与数据结构)