Chinaunix首页 | 论坛 | 博客
  • 博客访问: 164948
  • 博文数量: 56
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 593
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-18 09:59
文章分类

全部博文(56)

文章存档

2019年(1)

2018年(26)

2016年(1)

2015年(6)

2014年(22)

我的朋友

分类: Java

2014-03-24 22:41:42


说明
二分搜寻法每次搜寻时,都会将搜寻区间分为一半,所以其搜寻时间为O(log(2)n),log(2)表示
以2为底的log值,这边要介绍的费氏搜寻,其利用费氏数列作为间隔来搜寻下一个数,所以区
间收敛的速度更快,搜寻时间为O(logn)。
解法
费氏搜寻使用费氏数列来决定下一个数的搜寻位置,所以必须先制作费氏数列,这在之前有提
过;费氏搜寻会先透过公式计算求出第一个要搜寻数的位置,以及其代表的费氏数,以搜寻对
象10个数字来说,第一个费氏数经计算后一定是F5,而第一个要搜寻的位置有两个可能,例如
若在下面的数列搜寻的话(为了计算方便, 通常会将索引0订作无限小的数,而数列由索引1
开始):
-infin; 1 3 5 7 9 13 15 17 19 20
如果要搜寻5的话,则由索引F5 = 5开始搜寻,接下来如果数列中的数小于指定搜寻值时,就往
左找,大于时就向右,每次找的间隔是F4、F3、F2来寻找,当费氏数为0时还没找到,就表示
寻找失败,如下所示:

由于第一个搜寻值索引F5 = 5处的值小于19,所以此时必须对齐数列右方,也就是将第一个搜
寻值的索引改为F5+2 = 7,然后如同上述的方式进行搜寻,如下所示:


至于第一个搜寻值是如何找到的?我们可以由以下这个公式来求得,其中n为搜寻对象的个数:


如果数列number在索引5处的值小于指定的搜寻值,则第一个搜寻位置就是索引5的位置,如果
大于指定的搜寻值,则第一个搜寻位置必须加上m,也就是F5 + m = 5 + 2 = 7,也就是索引7的
位置,其实加上m的原因,是为了要让下一个搜寻值刚好是数列的最后一个位置。
费氏搜寻看来难懂,但只要掌握Fx + m = n这个公式,自己找几个实例算一次,很容易就可以理
解;费氏搜寻除了收敛快速之外,由于其本身只会使用到加法与减法,在运算上也可以加快。


点击(此处)折叠或打开

  1. /**
  2.  * @author:      吴永行
  3.  * @dateTime:     2014-3-24 下午10:13:33
  4.  * @description:     
  5.  *
  6.  */
  7. package 经典算法大全;

  8. import java.util.Random;
  9. import java.util.Scanner;

  10. public class _45_费氏搜寻法 {

  11.     /**
  12.      * @author:      吴永行
  13.      * @dateTime:     2014-3-24 下午9:25:31
  14.      * @description:     
  15.      * @param args
  16.      *
  17.      */

  18.     static final int MAX = 10;

  19.     static final void swap(int[] a, int i, int j) {
  20.         int t;
  21.         t = a[i];
  22.         a[i] = a[j];
  23.         a[j] = t;
  24.     }

  25.     static int Fib[] = new int[MAX];

  26.     public static void main(String[] args) {

  27.         int number[] = new int[MAX + 1];
  28.         int i, find = 0;
  29.         Random random = new Random();
  30.         System.out.format("排序前:");
  31.         for (i = 0; i < MAX; i++) {
  32.             number[i] = Math.abs(random.nextInt()) % 100;
  33.             System.out.format("%d ", number[i]);
  34.         }
  35.         quicksort(number, 1, MAX);
  36.         System.out.format("数列:");
  37.         for (i = 1; i <= MAX; i++)
  38.             System.out.format("%d ", number[i]);
  39.         System.out.format("\n输入搜寻值:");
  40.         Scanner in = new Scanner(System.in);
  41.         find = in.nextInt();
  42.         if ((i = fibsearch(number, find)) >= 0)
  43.             System.out.format("\n找到数值于索引%d ", i);
  44.         else
  45.             System.out.format("\n找不到数值");
  46.         System.out.format("\n");

  47.     }

  48.     /**
  49.      * @author:      吴永行
  50.      * @dateTime:     2014-3-24 下午9:28:17
  51.      * @description:     
  52.      * @param number
  53.      * @param find
  54.      * @return
  55.      *
  56.      */
  57.     private static int fibsearch(int[] number, int find) {
  58.         int i, x, m;
  59.         createfib();
  60.         for (int j : Fib) {
  61.             System.out.print(j+ "\t");
  62.         }
  63.         x = findx(MAX + 1, find);
  64.         m = MAX - Fib[x];
  65.         System.out.format("\nx = %d, m = %d, Fib[x] = %d\n\n", x, m, Fib[x]);
  66.         x--;
  67.         i = x;
  68.         if (number[i] < find)
  69.             i += m;
  70.         while (Fib[x] > 0) {
  71.             if (number[i] < find)
  72.                 i += Fib[--x];
  73.             else if (number[i] > find)
  74.                 i -= Fib[--x];
  75.             else
  76.                 return i;
  77.         }
  78.         return -1;
  79.     }

  80.     /**
  81.      * @author:      吴永行
  82.      * @dateTime:     2014-3-24 下午10:16:46
  83.      * @description:     
  84.      * @param i
  85.      * @param find
  86.      * @return
  87.      *
  88.      */
  89.     private static int findx(int n, int find) {

  90.         int i = 0;
  91.         while (Fib[i] <= n)
  92.             i++;
  93.         i--;
  94.         return i;
  95.     }

  96.     /**
  97.      * @author:      吴永行
  98.      * @dateTime:     2014-3-24 下午10:16:44
  99.      * @description:     
  100.      *
  101.      */
  102.     private static void createfib() {
  103.         int i;
  104.         Fib[0] = 0;
  105.         Fib[1] = 1;
  106.         for (i = 2; i < MAX; i++)
  107.             Fib[i] = Fib[i - 1] + Fib[i - 2];
  108.     }

  109.     /**
  110.      * @author:      吴永行
  111.      * @dateTime:     2014-3-23 下午9:41:21
  112.      * @description:     
  113.      * @param number
  114.      * @param i
  115.      * @param j
  116.      *
  117.      */
  118.     private static void quicksort(int[] number, int left, int right) {
  119.         int q;
  120.         if (left < right) {
  121.             q = partition(number, left, right);
  122.             quicksort(number, left, q - 1);
  123.             quicksort(number, q + 1, right);
  124.         }
  125.     }

  126.     /**
  127.      * @author:      吴永行
  128.      * @dateTime:     2014-3-23 下午9:42:02
  129.      * @description:     
  130.      * @param number
  131.      * @param left
  132.      * @param right
  133.      * @return
  134.      *
  135.      */
  136.     private static int partition(int[] number, int left, int right) {
  137.         int i, j, s;
  138.         s = number[right];
  139.         i = left - 1;
  140.         for (j = left; j < right; j++) {
  141.             if (number[j] <= s) {
  142.                 i++;
  143.                 swap(number, i, j);
  144.             }
  145.         }
  146.         swap(number, i + 1, right);
  147.         return i + 1;
  148.     }

  149. }


阅读(958) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~