zoukankan      html  css  js  c++  java
  • 算法_归并排序

      归并排序的基本思想是:将两个已经有序的数组,归并成为更大的有序数组.这种操作称为归并排序.要让一个数组排序,可以先递归的把它分成两半分别排序,然后将结果归并起来.归并排序能够保证对一个任意长度为N的数组排序所需时间和NlogN成正比.

      基本的归并方法代码如下:该方法先将所有的元素复制到aux[]中,然后再归并到a[]中.方法在归并的时候,进行了四次条件判断:左半边用尽(取右半边的元素),右半边用尽(取左半边的元素),右半边的当前元素小于左半边的当前元素(取右半边的元素)以及右半边的元素大于等于左半边的当前元素.

    private static void merge(Comparable[] a, int lo, int mid, int hi) {
            int i=lo;
            int j=mid+1;
            for(int k=lo;k<=hi;k++) {
                aux[k]=a[k];
            }
            for(int k=lo;k<=hi;k++) {
                if(i>mid) a[k]=aux[j++];
                else if(j>lo) a[k]=aux[i++];
                else if(less(aux[i],aux[j])) a[k]=aux[i++];
                else a[k]=aux[j++];
            }
        }

      利用上面的归并代码,可以产生两种排序方法,自顶向下和自底向上的排序算法,分别整理如下:

      自顶向下的算法认为:如果能够将两个子数组排序,就能够通过归并两个子数组来将整个数组进行排序:

    public class Merge {
        private static Comparable[] aux;
        public static void sort(Comparable[] a) {
            aux=new Comparable[a.length];
            sort(a,0,a.length-1);
        }
        public static void sort(Comparable[] a, int lo, int hi) {
            if(hi<=lo) return;
            int mid=lo+(hi-lo)/2;
            sort(a,lo,mid);            //左半边排序[[9
            sort(a,mid+1,hi);        //右半边排序.
            merge(a,lo,mid,hi);    //归并
        }
        private static void merge(Comparable[] a, int lo, int mid, int hi) {
            int i=lo;
            int j=mid+1;
            for(int k=lo;k<=hi;k++) {
                aux[k]=a[k];
            }
            for(int k=lo;k<=hi;k++) {
                if(i>mid) a[k]=aux[j++];
                else if(j>lo) a[k]=aux[i++];
                else if(less(aux[i],aux[j])) a[k]=aux[i++];
                else a[k]=aux[j++];
            }
        }
        public static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w)<0;
        }
    }

      自顶向下的归并排序对于长度为N的任意数组,需要1/2NlgN~NlgN次比较.(证明方法见算法第四版).此外归并排序还有可以优化的地方,如对于小规模的数组可以使用插入排序,可以添加判断条件,例如通过测试a[mid]小于等于a[mid+1],我们就认为数组已经是有序的并跳过merge方法.

      自底向上的归并排序利用先归并那些微型数组,然后再成对归并得到的子数组,如此这般,直到我们将整个数组归并在一起.自底向上的归并排序算法的实现如下:

    public class MergeBU {
        private static Comparable[] aux;
        
        public static void sort(Comparable[] a) {
            int N=a.length;
            aux=new Comparable[N];
            for(int sz=1;sz<N;sz=sz+sz) /*子数组的大小*/{
                for(int lo=0;lo<N-sz;lo+=sz+sz) /*lo:子数组的索引*/{
                    merge(a,lo,lo+sz-1,Math.min(lo+sz+sz-1, N));
                }
            }
        }
        public static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w)<0;
        }
        public static void merge(Comparable[] a,int lo,int mid,int hi) {
            int i=lo;
            int j=mid+1;
            for(int k=lo;k<=hi;k++) {
                aux[k]=a[k];
            }
            for(int k=lo;k<=hi;k++) {
                if(i>mid) a[k]=aux[j++];
                else if(j>lo) a[k]=aux[i++];
                else if(less(aux[i],aux[j])) a[k]=aux[i++];
                else a[k]=aux[j++];
            }
        }
    }

      对于任意的长度为N的任意数组,自底向上的归并排序需要1/2NlgN至NlgN次比较.最多访问数组6NlgN次.

  • 相关阅读:
    实验二
    实验一简单的加减乘除
    自我简介
    软件工程——第五次博客作业
    《软件测试》--第四次博客作业
    软件测试 第三次作业
    软件测试 第二次作业
    个人简介
    软件测试 第一次测评
    AE CC 装不上,安装程序检测到计算机重新启动的过程可能暂停。建议退出安装程序,重新启动计算机,然后再重试。
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5638972.html
Copyright © 2011-2022 走看看