斐波那契查找(超详解)
来源:互联网 发布:乔任梁受什么网络暴力 编辑:程序博客网 时间:2024/05/16 17:42
// 斐波那契查找.cpp #include <iostream> #include <string.h> using namespace std; const int max_size=20;//斐波那契数组的长度 /*构造一个斐波那契数组*/ void Fibonacci(int * F) { F[0]=0; F[1]=1; for(int i=2;i<max_size;++i) F[i]=F[i-1]+F[i-2]; } /*定义斐波那契查找法*/ int Fibonacci_Search(int *a, int n, int key) //a为要查找的数组,n为要查找的数组长度,key为要查找的关键字 { int low=0; int high=n-1; int F[max_size]; Fibonacci(F);//构造一个斐波那契数组F int k=0; while(n>F[k]-1)//计算n位于斐波那契数列的位置 ++k; int * temp;//将数组a扩展到F[k]-1的长度 temp=new int [F[k]-1]; memcpy(temp,a,n*sizeof(int)); /* strcpy和memcpy主要有以下3方面的区别。 1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。 2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。 3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy 4、包含在<string.h>中 5、函数原型:void *memcpy(void *dest, const void *src, size_t n); 功能:从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中*/ for(int i=n;i<F[k]-1;++i) temp[i]=a[n-1]; /* 首先要明确:如果一个有序表的元素个数为n,并且n正好是(某个斐波那契数 - 1),即n=F[k]-1时,才能用斐波那契查找法。 如果有序表的元素个n不等于(某个斐波那契数 - 1),即n≠F[k]-1,这时必须要将有序表的元素扩展到大于n的那个斐波那契数 - 1才行, 上面for循环这段代码:便是这个作用。 */ while(low<=high) { int mid=low+F[k-1]-1; if(key<temp[mid]) { high=mid-1; k-=1; } else if(key>temp[mid]) { low=mid+1; k-=2; } else { if(mid<n) return mid; //若mid<n则说明mid即为查找到的位置 else return n-1; //若mid>=n则说明是扩展的数值,返回n-1 } } /* 斐波那契查找方法的核心代码就是上面一段 原理: 1)当key=a[mid]时,查找成功; 2)当key<a[mid]时,新的查找范围是第low个到第mid-1个,此时范围个数为F[k-1] - 1个,即数组左边的长度, 所以要在[low, F[k - 1] - 1]范围内查找; 3)当key>a[mid]时,新的查找范围是第mid+1个到第high个,此时范围个数为F[k-2] - 1个,即数组右边的长度, 所以要在[F[k - 2] - 1]范围内查找。 4) 对于二分查找,分割是从mid= (low+high)/2开始;而对于斐波那契查找,分割是从mid = low + F[k-1] - 1开始的; 通过上面知道了,数组a现在的元素个数为F[k]-1个,即数组长为F[k]-1,mid把数组分成了左右两部分, 左边的长度为:F[k-1] - 1, 那么右边的长度就为(数组长-左边的长度-1), 即:(F[k]-1) - (F[k-1] - 1) = F[k] - F[k-1] - 1 = F[k-2] - 1。 */ delete [] temp; //释放new出来的内存,因为是数组,所以才去delete [] temp的方式而不是delete temp. return -1; } int main() { //int a[] = {0,10,24,35,47,59,62,73,88,99}; int a[]= {05,13,19,21,37,56,64,75,80,88,92}; int key=21; int index=Fibonacci_Search(a,sizeof(a)/sizeof(int),key); /* 这里插入讨论一下数组的长度问题: 1、char a[]=""类型的字符串,编译器会在结尾自动添加\0,用sizeof计算会算上'\0' 2、存在的C语言方法,如strlen(s),计算字符串的长度,其中s指针。strlen要计算字符串长度, 必须知道哪里是结尾,因此使用\0表示结尾。只有字符数组才有\0的概念,其它类型(int)的数组没有这个概念。 如int a[]={} 知道数组长度使用sizeof(a)/sizeof(int); 3、那么问题来了char a[]={}这种类型的字符串,用用sizeof计算会不会算上'\0'? 答案是不会的。 */ cout<<key<<" is located at:"<<index<<endl; system("PAUSE"); return 0; } /* 1、这里我首先建立了一个11个元素的数组a[],n=11,那么n就位于8和13,即F[6]和F[7]之间,所以 k=7, 此时数组a的元素个数要被扩充,为:F[7] - 1 = 12个 (这里如果问我为什么要扩充为F[k]-1而不是F[k],先留个问号,可以参考http://www.360doc.com/content/14/0528/10/14505022_381653345.shtml) 2、然后根据核心代码开始找数:我们要找值为13的元素 斐波那契数列前几位:0、1、1、2、3、5、8、13 1)mid=low+F[k-1]-1 则mid=7; 2)比较得key<temp[mid],则high=mid-1; k-=1; 即有high=6,k=6 3)入循环,mid=0+5-1=4; 4)比较得key<temp[mid],则high=mid-1; k-=1;,则有high=3,k=5 3)入循环,mid=0+3-1=2; 4)比较得key<temp[mid],则high=mid-1; k-=1;,则有high=1,k=4 5)入循环,mid=0+2-1=1; 6)知道mid<n,得到位置为1 3、最重要的是理解斐波那契查找的理念,让mid保持在数组的黄金分割点处,像一开始时,mid前面长度为F[K-1]-1,后面长度为F[K-2]-1,数组总长度为F[K]-1,mid 在黄金分割点。*/ /* 与二分查找比较:①斐波那契查找的平均性能比折半查找好,②但最坏情况下性能却比折半查找差,③它还有一个优点就是分割时只需进行加减运算。" 与二分查找相比,斐波那契查找算法的明显优点在于它只涉及加法和减法运算,而不用除法。 因为除法比加减法要占去更多的机时,因此,斐波那契查找的平均性能要比折半查找好。 */
1 0
- 斐波那契查找(超详解)
- 斐波那契查找(超详解)
- 斐波那契查找详解
- 斐波那契查找详解
- 静态查找(顺序查找,折半查找,插值查找,斐波那契查找)
- 斐波那契查找(数据结构)
- (1.3.2.2)查找:斐波那契查找
- 查找-斐波那契查找
- 算法--查找--斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- 斐波那契查找
- Java基础---面向对象(继承、多态、抽象类、接口、内部类)
- awk关系操作符
- opencv 在 ubuntu14.04 中的配置和测试
- leetcode--Bitwise AND of Numbers Range
- POJ 1183 反正切函数的应用(数论)
- 斐波那契查找(超详解)
- 2015年大一下第15周项目1-平方根中的异常
- First Missing Positive - LeetCode 41
- [leetcode] Letter Combinations of a Phone Number
- Struts2(四)文件上传
- 我看我自己系列——看自己不嘚瑟
- 《开源框架那点事儿17》:与屈原对话及开源精神
- UITableView_XIB实现_可重用Cell_封装步骤
- 03_Android项目中读写文本文件的代码