实验三-总结博客

实验三-查找与排序-3

参考http://www.cnblogs.com/maybe2030/p/4715035.html 在Searching中补充查找算法并测试
提交运行结果截图

斐波那契查找

  • 1.斐波那契数列
    斐波那契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、····,在数学上,斐波那契被递归方法如下定义:F(1)=1,F(2)=1,F(n)=f(n-1)+F(n-2) (n>=2)。该数列越往后相邻的两个数的比值越趋向于黄金比例值(0.618)。

  • 2.实现思路
    我认为斐波那契查找和二分查找的区别不大,唯一的区别是二分查找的划分是对半分,而斐波那契查找是根据斐波那契数列进行的划分。但我们知道斐波那契查找的算法复杂度依旧是O(log 2 n ),而且实现还很复杂,所以斐波那契查找相较于二分查找的好处是在每次计算mid的值的时候避免了"除法",只是涉及到了"加法和减法",而除法的运算本身就比加减法更加占用时间。
    如何进行查找。之所以斐波那契查找避免了除法,是因为我们一开始构造了一个斐波那契数列,每次划分只需要从数列中拿出相应的两个数就行。斐波那契数列:1、1、2、3、5、8、13、21、34、55、89……从第三个数开始,每个数等于前两个数的和,巧妙利用这一点我们在每次比较后对于mid的赋值就不必像二分查找mid = (first + last ) / 2,而是mid = first+fib[idex-1]-1,fib是我们构造的一个斐波那契数列,正是要利用斐波那契数列的特点进行分割,我们就必须根据要进行查找的数组来从fib数组中确定一个数m.这里会出现两种情况:(1)数组长度刚好符合fib数列中的某个数;(2)fib数组找不到恰当的数,这时候就需要将原数组进行扩充,我们采用重复填入最后一个数。如果m = fib[n],那么第一次划分就将数组分为两个部分它们分别含有fib[n-1]和fib[n-2]个元素,然后进行比较,再根据比较的结果再对数组进行划分。

    public static Comparable FibonacciSearch(Comparable[] data, Comparable target) {
        int idex = 0;
        int[] fib = SetFibonacci();
        while (data.length>fib[idex]){
            idex++;
        }
        Comparable[] fibdata = new Comparable[fib[idex]];
        ;
        for (int i = 0;i<fibdata.length;i++){
            if (i<data.length){
                fibdata[i] = data[i];
            }
            else
                fibdata[i] = data[data.length-1];
        }
        int first=0;
        int last = fibdata.length-1;
        int mid = 0;
        while (first<= last){
                mid = first+fib[idex-1]-1;
                if (fibdata[mid].compareTo(target)>0){
                    last = mid;
                    idex = idex-1;
                }
                else if (fibdata[mid].compareTo(target)<0){
                    first = mid;
                    idex = idex-2;
                }
                else {
                    if (mid<=last)
                        return mid;
                    else
                        return last;
                }
        }
        return -1;
    }
    //构造Fibonacci数列
    public static int[] SetFibonacci() {
        int[] fib = new int[20];
        int i = 0;
        fib[0] = 1;
        fib[1] = 1;
        for (i = 2; i < fib.length; i++) {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
        return fib;
    }

插值查找

  • 原理:插值查找的主要思路就是划分数组的查找点是自适应,所以该查找的前提是有序数列元素的值是成线性增长的。

二分查找中查找点计算如下:
  mid=(low+high)/2, 即mid=low+1/2(high-low);
  通过类比,我们可以将查找的点改进为如下:
  mid=low+(key-a[low])/(a[high]-a[low])
(high-low),
  也就是将上述的比例参数1/2改进为自适应的,根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。

  • 加入我们要在[1,100]中找到15,我们设15的下标为m,第一个数的下标(first),第二个数的下标(last),由于数列线性增长,我们不难得到(m-first)/(last-first) ≈ (15-A[first])/(A[last]-A[first])进而得到:m = first + (15-A[first])/(A[last]-A[first])*(last-first).
public static Comparable InsertionSearch(Comparable[] data, Comparable target, int key, int low, int hight) {
        if (key < low || key > hight || low < hight) {
            throw new NumberFormatException("Wrong number");
        } else {
            int mid;
            Comparable result = null;
            while (result == null && low <= hight) {
                mid = low + (key - low) / (hight - low) * (hight - low);
                if (data[mid].compareTo(target) == 0) {
                    result = data[mid];
                } else if (data[mid].compareTo(target) > 0)
                    hight = mid - 1;
                else
                    low = mid + 1;
            }
            return result;
        }
    }

实验三-查找与排序-4

补充实现课上讲过的排序方法:希尔排序,堆排序,桶排序,二叉树排序等
测试实现的算法(正常,异常,边界)
提交运行结果截图
推送相关代码到码云上

堆排序

  • 利用已经完善的类LinkedMaxHeap,现将要排序的数组的元素加入到堆(最大)中,利用removeMax()方法将元素按照从大到小输出。
public static void HeapSort(Comparable[] data){
      LinkedMaxHeap myTree = new LinkedMaxHeap();
      for (int i=0;i<data.length;i++){
         myTree.add(data[i]);
      }
      for (int i=0;i<data.length;i++){
         data[i]=myTree.removeMax();
      }
   }
posted @ 2017-11-12 22:51  Wb同学在此  阅读(199)  评论(0编辑  收藏  举报