查找算法1-Fibonacci查找

斐波那契查找是一种在有序表中高效查找指定元素的算法,比折半查找要复杂一些,主要复杂在要多做不少准备工作。下面看它的工作流程:

1.计算并保存一个斐波那契序列的数组,方便以后取值。数组名记为f,例如f[1]=1,f[2]=1,f[3]=2,f[4]=3,f[5]=5,f[6]=8,f[7]=13,f[8]=21

2.把有序数组的长度扩充到a.length=f[k]-1,k是满足条件的最小值,比如数组长度为13,那么就把它长度扩充到f[8]-1=20,所有在末尾添加的扩充元素都是原数组最后一个元素的复制品

3.找到mid元素,不断进行二分比较,直到找到目标元素为止,这一步的做法与折半查找一模一样,仅仅是计算mid的公式从(low+high)/2改为low+(f[k-1]-1)。

        斐波那契查找的理解难点就一个:为什么需要把数组长度扩充到f[k]-1而不是f[k]或者
f[k+1]?
这是为了能正确递归计算mid值,看下图可发现 f[k]-1 = (f[k-1] + f[k-2]) - 1 =
(f[k-1]-1) + 1
+ (f[k-2]-1),中间的1就是我们二分的锚点mid,如果目标在左区,数组长度就缩到(f[k-1]-1),如果在右区,数组长度就缩到
(f[k-2]-1),否则就等于mid完成查找。而(f[k-1]-1)又能拆成(f[k-2]-1)+1+(f[k-3]-1),这样递归分割下去就
能不断的缩小区间直至找到目标。

#include <stdio.h>
#define LEN 9
#define MAXSIZE 100

int F[50];//fibonacci数列
//构造fibonacci数列
void FibonacciArray(int * a){
    int i;
    a[0]=1;
    a[1]=1;
    for(i=2; i<50; i++){
        a[i]=a[i-1]+a[i-2];
    }
}

//进行fibonacci查找,返回0即查找失败,否则返回找到的下标
int FibonacciSearch(int * a,int n,int key){
    int k=0,i;
    int mid,low=1,high=n;
    while(n>F[k]-1)
        k++;//确定初始k值

    for(i=n+1; i<=F[k]-1; i++ ){
        a[i]=a[n];    //补全a[n+1]到a[F[k]-1],使之都==a[n]
    }
    //开始查找
    while(low<=high){//注意
        mid=low+F[k-1]-1;
        if(a[mid]>key){//如果中间值比要查找的值大
            high=mid-1;
            k=k-1;
        }else if(a[mid]<key){
                low=mid+1;
                k=k-2;
            }else{//a[mid]==key
                if(mid<=n) return mid;
                    else if(mid>n)//说明找到的下标在原来填补的位置上,是和a[n]相同的,所以返回n
                        return n;
            }

    }
    return 0;//返回0,即key不在数组a中
}
int main(){

int a[LEN+1]={0,8,23,45,78,89,25,68,47,59};//设首位为哨兵
int arr[MAXSIZE]={0};//设一个足够大的数组,代入函数计算
for(int i=0; i<LEN+1; i++){
    arr[i]=a[i];
}

int result;
int key=59;
FibonacciArray(F);//返回[1,1,2,3,5,...]
//printf("%d",F[7]);
result=FibonacciSearch(arr,LEN,key);
if(result!=0){
    printf("%d存在数组a中,等于a[%d]\n",key,result);
}else
    printf("数组a中不存在%d\n",key);

return 0;
}

结果:

之前写的时候返了一个错误,while(low<=high)小于等于写成了<;

参考:

[1]大话数据结构,p.303-304

[2]http://blog.csdn.net/lzdidiv/article/details/59784694

时间: 2024-11-20 11:42:12

查找算法1-Fibonacci查找的相关文章

查找算法:二分查找、顺序查找

08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活.此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/details/7747205 查找算法 查找算法是在存在的序列(list) 中查找特定的目标(target),要求序列中每个记录必须与一个关键词(key)关联才能进行查找. 查找算法通常需要两个输入: 1.被查找的序列 2.要查找的关键词 查找算法的输出参数和返回值: 1.返回类型为 Error_co

Java中的查找算法之顺序查找(Sequential Search)

Java中的查找算法之顺序查找(Sequential Search) a) 原理:顺序查找就是按顺序从头到尾依次往下查找,找到数据,则提前结束查找,找不到便一直查找下去,直到数据最后一位. b) 图例说明: 原始数据:int[] a={4,6,2,8,1,9,0,3}; 要查找数字:8 找到数组中存在数据8,返回位置. 代码演示: import java.util.Scanner; /* * 顺序查找 */ public class SequelSearch { public static vo

算法学习之查找算法:动态查找表(1)二叉排序树

引言: 动态查找表的特点是,在表结构本身是在查找过程中动态生成的,即对于给定值key,若表中存在其关键字等于key的记录,则查找成功返回,否则插入关键字等于key的记录. 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: 1.若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值. 2.若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值. 3.它的左.右子树也分别为二叉排序树. <一>二叉排序树的查找: 二叉排序树又称二叉查找树,查找过程是先将给定值和根结点的关键字比较,

Java学习 (七)、数组,查找算法,二分查找法,冒泡排序,选择排序,插入排序

一.常用数组查找算法 工作原理:它又称为顺序查找,在一列给定的值中进行搜索,从一端的开始逐一检查每个元素,知道找到所需元素的过程. 例1:查找指定的数在数组中出现的位置,找到返回下标,找不到返回-1 1 import java.util.Scanner; 2 public class LinearSearch{ 3 public static void main(String []argas) 4 { 5 int [] array={10,100,90,65,80,92}; 6 System.o

顺序查找算法和二分查找算法

顺序查找算法 int lin_Search(const int array[],int size,int key) { int index; for (index = 0;index <= size-1;++index) if (key==array[index]) return index; return -1; } 二分查找算法 int bin_Search(const int array[],int low,int high,int key) { int index; while ( hi

Java查找算法(二): 顺序查找

[ 什么是顺序查找 ]  顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从表中第一个或最后一个记录开始,逐个和给定的值比较,如相等则查找成功:如直到最后一个值仍不等时,则表中没有所查的记录,查找不成功. [ Java实现顺序查找 ]  public class SequentialSearch { public static void main(String[] args) { Integer target = 6; Integer[] iArr = { 3, 2, 6, 8, 5,

2. C#数据结构与算法 -- 查找算法(顺序查找,哈希查找,二分查找(折半),索引,二叉)

1. 顺序查找算法 ===================================================== 算法思想简单描述: 最突出的查找类型就是从记录集的开始处顺次遍历每条记录,直到找到所要的记录或者是 到达数据集的末尾.这就是所谓的顺序查找.顺序查找(也被称为线性查找)是非常容易实现 的.从数组的起始处开始,把每个访问到的数组元素依次和所要查找的数值进行比较.如果找 到匹配的数据项,就结束查找操作.如果遍历到数组的末尾仍没有产生匹配,那么就说明此数 值不在数组内. ==

I学霸官方免费教程二十九:Java查找算法之二分法查找

二分法查找算法 基本步骤:    第一步:获取数组中间的下标    第二步:中间下标处的值和目标值比较,如果目标值大,说明要找的值在数组的后边一半中    第三步:再次获取数组右边一半的中间下标    第四步:再次用获得的中间下标和目标值进行比较    后续步骤以此类推,这样每次查找都在"半份"数据中进行,所以又叫折半查找.这也是为什么使用二分法查找之前必须要对数组进行排序的原因.如果不排序,将无法判断目标值在哪"半份"中 实例: package algorithm

【Java_Base】常用查找算法:顺序查找、二分查找

顺序查找 从第一个元素开始顺序比较查找. 二分查找 二分查找前提条件: 已排序的数组中查找 二分查找的基本思想是: 首先确定该查找区间的中间点位置: int mid = (low+upper) / 2; 然后将待查找的值与中间点位置的值比较: 若相等,则查找成功并返回此位置. 若中间点位置值大于待查值,则新的查找区间是中间点位置的左边区域. 若中间点位置值小于待查值,则新的查找区间是中间点位置的右边区域. 下一次查找是针对新的查找区间进行的. 1 public class Search{ 2 p

查找算法(二分查找)

1.二分查找介绍 #描述二分查找: 二分查找针对有序的数据集合,要从有序集合中,找出目标值.每次都把目标值,与区间的中间元素进行对比,将待查找的区间缩小为之前的一半,直到查到要查找的目标元素.或者区间缩小为0. #二分查找实现注意事项: 1.循环退出条件 low<=high 2.mid取值 普通方式:mid=(low+high)/2 改进方式:mid=low+(high-low)/2 终极方式:mid=low+((high-low)>>1) 3.low和high更新 low=mid+1