`
bcyy
  • 浏览: 1819041 次
文章分类
社区版块
存档分类
最新评论

斐波那契数列算法 Fibonacci Search 优化二分法查找算法

 
阅读更多

二分法已经非常快速了,但是还是可以改进二分法查找:

不要使用中间元素, 而是使用更为精确的区间,找到关键字在上面区间内,使其收敛更快。

使用Fibonacci序列数字来确定这个区间,就是Fibonacci Search。

二分法请参考:

http://blog.csdn.net/kenden23/article/details/16113241

下面是Wiki对Fibonacci Search的叙述:

To test whether an item is in the list of ordered numbers, follow these steps:

  1. Set k = m.
  2. If k = 0, stop. There is no match; the item is not in the array.
  3. Compare the item against element in Fk−1.
  4. If the item matches, stop.
  5. If the item is less than entry Fk−1, discard the elements from positions Fk−1+1 to n. Set k=k−1 and return to step 2.
  6. If the item is greater than entry Fk−1, discard the elements from positions 1 to Fk−1. Renumber the remaining elements from 1 to Fk−2, set k=k−2, and return to step2.

参考:Wiki

下面就根据这个算法一步一步实现这个程序:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

void generateFibonacci(vector<int> &fibvec, int n)
{
	if(n>47) n = 47;	//整形数据只能存在47个fibonacci元素了。这里的fibonacci第一个数是0.
	fibvec.push_back(0);
	fibvec.push_back(1);
	for (int i = 2; i < n; i++)
	{
		fibvec.push_back(fibvec[i-1] + fibvec[i-2]);
	}
}

template<typename T>
int fibonacciSearch(vector<T> &vt, T key)
{
	vector<int> fibvec;
	generateFibonacci(fibvec, 47);
	int n = vt.size();

	//1.Set k = m.
	int k = lower_bound(fibvec.begin(), fibvec.end(), n) - fibvec.begin();
	
	//offset is needed for recording the begin point in vt.
	int offset = 0;
	int index = 0;
	//2.If k = 0, stop. There is no match; the item is not in the array.
	while (k>0)
	{
		index = fibvec[--k]+offset;
		//3.Compare the item against element in Fk−1.
		//5.If the item is less than entry Fk−1, discard the elements from positions Fk−1 + 1 to n. Set k = k − 1 and return to step 2.
		//注意:这里的index有可能大于数组最大值n的。因为fibvec[k]有可能远远大于n,那么fibvec[k-1]+offset就有可能也大于n。注意这个特殊情况。比如数组元素有22个,那么就要选取fibvec[k] == 34。那么fibvec[k-1] == 21,第二趟循环的时候offset有可能变成21,那么f[k]==13,f[k-1]==8那么就很容易超标!
		if(index>=n || key < vt[index]) continue;
		//6.If the item is greater than entry Fk−1, discard the elements from positions 1 to Fk−1. Renumber the remaining elements from 1 to Fk−2, set k = k − 2, and return to step 2.
		else if (key > vt[index])
		{
			offset = index;
			k--;
		}
		//4.If the item matches, stop.
		else return index;
		
	}
	return -1;
}

int main()
{
	std::vector<int> vec;

	// set some initial content:
	for (int i=1;i<10;i++) vec.push_back(i<<2);

	vec.resize(7);
	vec.resize(12,80);

	std::cout << "vec contains:";
	for (int i=0;i<vec.size();i++)
		std::cout << ' ' << vec[i];
	std::cout << '\n';
	cout<<endl<<"Fibonacci List:\n";
	vector<int> fibvec;
	generateFibonacci(fibvec, 120);
	for (auto x:fibvec)
		cout<<x<<" ";
	cout<<endl<<endl;;

	cout<<"Fibonacci Search: ";
	int fibnd = fibonacciSearch(vec, 28);
	cout<<fibnd;
	if(fibnd != -1)
		cout<<"\tValue: "<<vec[fibnd]<<endl;
	else cout<<"\tNo Found!"<<endl;

	system("pause");
	return 0;
}


主要注意这个容易出错的地方:这里的index有可能大于数组最大值n的。因为fibvec[k]有可能远远大于n,那么fibvec[k-1]+offset就有可能也大于n。注意这个特殊情况。比如数组元素有22个,那么就要选取fibvec[k] == 34。那么fibvec[k-1] == 21,第二趟循环的时候offset有可能变成21,那么f[k]==13,f[k-1]==8那么就很容易超标!

运行结果:

分享到:
评论

相关推荐

    算法设计与分析PPT(C语言完整版)

    3.4.4斐波那契数列的应用 3.4.5递推关系求解方程 习题 第三篇核心篇 第4章基本的算法策略4.1迭代算法 4.1.1递推法 4.1.2倒推法 4.1.3迭代法解方程 4.2蛮力法 4.2.1枚举法 4.2.2其他范例 4.3分治算法 4.3.1分治算法...

    易语言经典算法

    斐波那契数列(递推法) 分块查找 求帕斯卡三角(杨辉三角) 箱子问题(贪婪法) 寻找文件(递归法) 求最大公约数(递归法) 取不重复数(排除法) 拉丁方 波松瓦分酒 皇后问题 背包问题 角谷猜想 邮票组合 贮油点 分解质因数 ...

    python 实现 数学中经典问题 课程设计 代码

    熵,欧几里得距离,欧几里得最大公约数,欧拉方法,改进欧拉方法,欧拉函数,扩展欧几里得算法,阶乘,因数,费马小定理,斐波那契数列,查找最大值,递归查找最大值,查找最小值,递归查找最小值,下取整,伽马函数...

    Algorithms-and-data-structures---Java:自己根据书C语言版算法数据结构和一些资料,用Java实现其中经典的语法和算法结构

    算法与数据结构---Java版 根据书C语言版算法数据结构和...06 递归、三角数、Fibonacci数列 07 汉诺塔的实现 08 希尔排序 09 快速排序 10 二叉树的基本操作 11 二叉树先序、中序、后序遍历、删除节点 12 ...陆续更新中

    易语言5.0自带源代码[经典数学算法集.rar]

    23.斐波那契数列(递推法) 24.分块查找 25.求帕斯卡三角(杨辉三角) 26.箱子问题(贪婪法) 27.寻找文件(递归法) 28.求最大公约数(递归法) 29.取不重复数(排除法) 30.拉丁方 31.波松瓦分酒 32.皇后问题 33.背包问题 34....

    C语言中常见问题的算法与程序总结

    二十、斐波那契数 13 二十一、亲和数 14 二十二、欧拉数 14 二十三、欧拉的其他公式 15 二十四、欧拉方程 15 二十五、勾股数的特点 16 二十六、勾股数系的系和组 17 二十七、勾股数系的性质 17 二十八、二元一次不定...

    C程序范例宝典(基础代码详解)

    实例138 斐波那契数列 206 实例139 角谷猜想 207 实例140 哥德巴赫猜想 208 实例141 四方定理 209 实例142 尼科彻斯定理 210 4.5 逻辑推理与判断 211 实例143 魔术师的秘密 211 实例144 婚礼上的谎言...

Global site tag (gtag.js) - Google Analytics