zoukankan      html  css  js  c++  java
  • 13、【查找算法】斐波那契查找

    斐波那契查找

      在介绍斐波那契查找算法之前,我们先介绍一下很它紧密相连并且大家都熟知的一个概念——黄金分割。

      黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。

      0.618被公认为最具有审美意义的比例数字,这个数值的作用不仅仅体现在诸如绘画、雕塑、音乐、建筑等艺术领域,而且在管理、工程设计等方面也有着不可忽视的作用。因此被称为黄金分割。

      大家记不记得斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。

      基本思想:也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。
      相对于折半查找,一般将待比较的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个,所以可以递归 的应用斐波那契查找。

      复杂度分析:最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n)。

    C++实现源码:

      1 //斐波那契查找
      2 #include <iostream>
      3 #include <stdlib.h>
      4 #include <stdio.h>
      5 #include <cstring>
      6 #include <ctime>
      7 
      8 using namespace std;
      9 
     10 #define MAX 100
     11 #define max_size 150
     12 
     13 //数组输入
     14 void input(int *arr)
     15 {
     16     srand((unsigned)time(NULL));
     17     for(int i = 0; i < MAX; i++)
     18     {
     19         arr[i] = rand()%100;
     20     }
     21 }
     22 //数组输出
     23 void output(int *arr)
     24 {
     25     for(int i = 0; i < MAX; i++)
     26     {
     27         printf("%5d", arr[i]);
     28         if(0 == (i+1) % 10)
     29             cout << endl;
     30     }
     31     cout << endl;
     32 }
     33 //快速排序
     34 void quickSort(int *arr, int l, int h)
     35 {
     36     if(l < h)
     37     {
     38         int low, high, tmp;
     39         low = l;
     40         high = h;
     41 
     42         tmp = arr[l];//选择基准值
     43         //将数组按照基准值分为两部分
     44         while(low < high)
     45         {
     46             while(low < high && arr[high] > tmp)
     47                 high--;
     48             if(low < high)
     49                 arr[low++] = arr[high];
     50             while(low < high && arr[low] < tmp)
     51                 low++;
     52             if(low < high)
     53                 arr[high--] = arr[low];
     54         }
     55         arr[low] = tmp;
     56         //递归排序
     57         quickSort(arr, l, low-1);
     58         quickSort(arr, low+1, h);
     59     }
     60 }
     61 //构造一个斐波那契数组
     62 void fibonacci(int * F)
     63 {
     64     F[0] = 0;
     65     F[1] = 1;
     66     for(int i = 2; i < max_size; i++)
     67         F[i] = F[i-1] + F[i-2];
     68 }
     69 //斐波那契查找
     70 int fibonacciSearch(int *arr, int len, int value)
     71 {
     72     int low = 0;
     73     int high = len-1;
     74 
     75     int F[max_size];
     76     fibonacci(F);//构造一个斐波那契数组
     77 
     78     int k = 0;
     79     while(len > F[k]-1)//计算n位于斐波那契数组中的位置
     80         k++;
     81 
     82     int *temp;//将数组arr扩展到F[k]-1长度
     83 
     84     temp=new int [F[k]-1];
     85     memcpy(temp, arr, len*sizeof(int));
     86 
     87     for(int i = len; i < F[k]-1; i++)
     88         temp[i] = arr[len-1];
     89 
     90     while(low < high)
     91     {
     92         int mid = low + F[k-1]-1;
     93         if(value < temp[mid])
     94         {
     95             high = mid -1;
     96             k -= 1;
     97         }
     98         else if(value > temp[mid])
     99         {
    100             low = mid+1;
    101             k -= 2;
    102         }
    103         else
    104         {
    105             if(mid < len)
    106                 return mid;
    107             else
    108                 return len-1;
    109         }
    110     }
    111     delete[] temp;
    112     return -1;
    113 }
    114 
    115 
    116 int main()
    117 {
    118     int x, pos, num[MAX];
    119     input(num);
    120 
    121     cout << "sort before:" << endl;
    122     output(num);
    123     quickSort(num, 0, MAX-1);
    124     cout << "sort after:" << endl;
    125     output(num);
    126 
    127     cout << "Enter find num : ";
    128     cin >> x;
    129 
    130     pos = fibonacciSearch(num, MAX, x);
    131     if(pos)
    132         cout << "OK!" << x << "is found in pos : " << pos << endl;
    133     else
    134         cout << "Sorry!" << x << "is not found in num" << endl;
    135 
    136     return 0;
    137 }
  • 相关阅读:
    Cookie操作
    C# 操作Cookie类
    面向对象之struct
    高薪程序员都避开了那些坑【安晓辉】
    [转]C#之反射
    [转]正则表达式相关:C# 抓取网页类(获取网页中所有信息)
    membership 在web.config中配置信息
    面向对象之virtual
    面向对象之多态
    JAVA面向对象 接口
  • 原文地址:https://www.cnblogs.com/Long-w/p/9799128.html
Copyright © 2011-2022 走看看