查找算法(4)--Fibonacci search--斐波那契查找
1.斐波那契查找
(1)说明
在介绍斐波那契查找算法之前,我们先介绍一下很它紧密相连并且大家都熟知的一个概念——黄金分割。
黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。
0.618被公认为最具有审美意义的比例数字,这个数值的作用不仅仅体现在诸如绘画、雕塑、音乐、建筑等艺术领域,而且在管理、工程设计等方面也有着不可忽视的作用。因此被称为黄金分割。
大家记不记得斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。

(2)基本思想
也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。
相对于折半查找,一般将待比较的key值与第mid=(low+high)/2位置的元素比较,比较结果分三种情况:
[1]相等,mid位置的元素即为所求
[2]>,low=mid+1;
[3]<,high=mid-1。
斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;
开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种
[1]相等,mid位置的元素即为所求
[2]>,low=mid+1,k-=2;
说明:low=mid+1说明待查找的元素在[mid+1,high]范围内,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个,所以可以递归 的应用斐波那契查找。
(3)复杂度分析
最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n)。
2.代码
public final static int MAXSIZE = 20;
/**
* 斐波那契数列
*
* @return
*/
public static int[] fibonacci() {
int[] f = new int[MAXSIZE];
int i = 0;
f[0] = 1;
f[1] = 1;
for (i = 2; i < MAXSIZE; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
} public static int fibonacciSearch(int[] data, int key) {
int low = 0;
int high = data.length - 1;
int mid = 0;
//斐波那契分割数值下标
int k = 0;
//序列元素个数
int i = 0;
// 获取斐波那契数列
int[] f = fibonacci();
//获取斐波那契分割数值下标
while (data.length > f[k] - 1) {
k++;
}
//创建临时数组
int[] temp = new int[f[k] - 1];
for (int j = 0; j < data.length; j++) {
temp[j] = data[j];
}
//序列补充至f[k]个元素
//补充的元素值为最后一个元素的值
for (i = data.length; i < f[k] - 1; i++) {
temp[i] = temp[high];
}
//打印
for (int j : temp) {
System.out.print(j + " ");
}
System.out.println();
//开始查找
while (low <= high) {
// low:起始位置
// 前半部分有f[k-1]个元素,由于下标从0开始
// 则-1 获取 黄金分割位置元素的下标
mid = low + f[k - 1] - 1; if (temp[mid] > key) {
// 查找前半部分,高位指针移动
high = mid - 1;
// (全部元素) = (前半部分)+(后半部分)
// f[k] = f[k-1] + f[k-1]
// 因为前半部分有f[k-1]个元素,所以 k = k-1
k = k - 1;
} else if (temp[mid] < key) {
// 查找后半部分,高位指针移动
low = mid + 1;
// (全部元素) = (前半部分)+(后半部分)
// f[k] = f[k-1] + f[k-1]
// 因为后半部分有f[k-1]个元素,所以 k = k-2
k = k - 2;
} else {
//如果为真则找到相应的位置
if (mid <= high) {
return mid;
} else {
//出现这种情况是查找到补充的元素
//而补充的元素与high位置的元素一样
return high;
}
}
}
return -1;
} public static void main(String[] args) {
int[] f = fibonacci();
for (int i : f) {
System.out.print(i + " ");
}
System.out.println();
int[] data = {1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68, 88};
int search = 39;
int position = fibonacciSearch(data, search);
System.out.println("值" + search + "的元素位置为:" + position);
}
查找算法(4)--Fibonacci search--斐波那契查找的更多相关文章
- 【算法】Fibonacci(斐波那契数列)相关问题
		
一.列出Fibonacci数列的前N个数 using System; using System.Collections.Generic; using System.Linq; using System ...
 - 斐波那契查找(Fibonacci Search)
		
斐波那契查找 斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的. 在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为F[n](如果要补充元素,则补充重复 ...
 - 【Java】 大话数据结构(10) 查找算法(1)(顺序、二分、插值、斐波那契查找)
		
本文根据<大话数据结构>一书,实现了Java版的顺序查找.折半查找.插值查找.斐波那契查找. 注:为与书一致,记录均从下标为1开始. 顺序表查找 顺序查找 顺序查找(Sequential ...
 - python实现斐波那契查找
		
通过在网上找教程解释和看书,总结出一套比较简单易懂的代码实现. 斐波那契查找和二分查找一样,针对的是有序序列,在此前提下: # 先创建一个Fibonacci函数 fib = lambda n: n i ...
 - 10、end关键字和Fibonacci series: 斐波纳契数列
		
# Fibonacci series: 斐波纳契数列 # 两个元素的总和确定了下一个数 a, b = 0, 1 #复合赋值表达式,a,b同时赋值0和1 while b < 10: print(b ...
 - 算法 递归 迭代 动态规划 斐波那契数列 MD
		
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
 - 《BI那点儿事》Microsoft 时序算法——验证神奇的斐波那契数列
		
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10 ...
 - 基于visual Studio2013解决算法导论之045斐波那契堆
		
 题目 斐波那契堆 解决代码及点评 // 斐波那契堆.cpp : 定义控制台应用程序的入口点. // #include<iostream> #include<cstdio> ...
 - Fibonacci series(斐波纳契数列)的几种常见实现方式
		
费波那契数列的定义: 费波那契数列(意大利语:Successione di Fibonacci),又译费波拿契数.斐波那契数列.斐波那契数列.黄金切割数列. 在数学上,费波那契数列是以递归的方法来定义 ...
 - [LeetCode] Fibonacci Number 斐波那契数字
		
The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such th ...
 
随机推荐
- 直接将字典转为DataFrame格式时,会出现:ValueError: If using all scalar values, you must pass an index(四种解决方案)
			
问题:想要将字典直接转为DataFrame格式时,除了字典外没有传入其他参数时,会报错 ValueError: If using all scalar values, you must pass an ...
 - NameValueCollectionValueProvider
			
NameValueCollectionValueProvider provider = new NameValueCollectionValueProvider(nameValueCollection ...
 - cmds jdbc连接写法
			
格式一: Oracle JDBC Thin using a ServiceName: jdbc:oracle:thin:@//<host>:<port>/<servic ...
 - 第3章 常用linux命令 3.5 文件压缩命令
			
实验六 文件及目录的压缩解压缩相关命令的使用 [实验目的] 1.掌握linux压缩文件实质 2.掌握linux中压缩及解压缩指令的用法 [实验环境] 1. 标准配置PC一台 2. linux操作系统: ...
 - Chrome插件安装和用法
			
XPath Helper 下载插件,拖入chrome://extensions/ 使用方法:ctrl+shift+x呼出 JSONView的使用: 安装JSONView插件 下载插件,拖入chrome ...
 - 优化sql技巧
			
当表很大的时候可以设计冗余字段,避免与大表连表查询造成性能低下 比如日志表和用户表,日志表通常到后期会相当的大可以做一个username的冗余字段,避免查看username的时候去和user表关联 当 ...
 - Numpy | 07 从数值范围创建数组
			
numpy.arange ***** 使用numpy 包中的 arange 函数,创建数值范围并返回 ndarray 对象,函数格式如下: numpy.arange(start, stop, step ...
 - luogu_2605: 基站选址
			
洛谷2605:基站选址 题意描述: 有\(N\)个村庄在一条直线上,第\(i(i>1)\)个村庄的距离第\(1\)个村庄的距离为\(D_i\). 需要在这些村庄中建立不超过\(K\)个通讯站,在 ...
 - [RN] React Native 再按一次退出
			
实现 React Native 再按一次退出 单页面: ... componentWillMount() { BackHandler.addEventListener('hardwareBackPre ...
 - on bind live delegate的区别
			
bind()----直接绑定在元素上 live()----通过冒泡的方式绑定到元素上,更适合于列表类型的绑定,和bind()相比,支持动态数据 delegate()----精确的小范围的适用事件代理, ...