Nathan Yan

想要出类拔萃,就要努力至少一万小时

归并排序 Merge sort

是一种简单的排序方法。时间复杂度为 O(N*logN)

思想:归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

可以看出合并有序数列的效率是比较高的,可以达到O(n)

解决了上面的合并有序数列问题,再来看归并排序,基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?

可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。

归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。

public class MergeSort {
      public static final int CUTOFF = 11;

      public static void main(String[] args) {
             // TODO Auto-generated method stub
             int[] a;
             int n = 300;
             // 生产随机数组
            a = new int[n];
            Random rand = new Random();
             for ( int i = 0; i < a. length; i++) {
                  a[i] = rand.nextInt(n);
            }
             //a = new int [] {33,10,80};
             println(a);

             long s = System. nanoTime();
             int[] b = mergeSort(a);
             long dur = System. nanoTime() - s;
             println(b);
            System. out.println(dur);

      }

      public static int[] mergeSort( int[] a) {
             int[] tmp = new int[a. length];
             split(a, tmp, 0, a.length-1);
             return tmp;
      }

      public static void split(int[] a, int[] tmp, int left, int right) {
             //System.out.println(left+","+right);
             if (left < right) {
                   int center = (left + right) / 2;
                   //System.out.println(center);
                   split(a, tmp, left, center);
                   split(a, tmp, center + 1, right);
                   merge(a,tmp,left,center+1,right);
            }
             //System.out.println("返回");
      }
    public static void merge(int[] a,int[] tmp,int lPos,int rPos,int rEnd){
      //System.out.println("merge:"+lPos+","+rPos+","+rEnd);
      int lEnd = rPos -1;
      int tPos = lPos;   
      int leftTmp = lPos;
      while(lPos <= lEnd && rPos <= rEnd){
             if(a[lPos] <= a[rPos]){
                  tmp[tPos++] = a[lPos++];
            } else{
                  tmp[tPos++] = a[rPos++];
            }           
      }
      
      while(lPos <= lEnd){
            tmp[tPos++] = a[lPos++];
      }
      
      while(rPos <= rEnd){
            tmp[tPos++] = a[rPos++];
      }
      // copy the tmpArr back cause we need to change the arr array items.
      for ( ; rEnd >= leftTmp; rEnd-- )
            a[rEnd] = tmp[rEnd];
      
    }

      public static void println(int[] a) {
            System. out.print( "[");
             for ( int i = 0; i < a. length; i++) {
                  System. out.print(a[i]);
                   if (i != a. length - 1)
                        System. out.print( ",");
            }
            System. out.println( "]");
      }

}











阅读更多
文章标签: 排序算法
个人分类: 算法-排序
上一篇Hadoop HDFS 数据一致性
下一篇插入排序 Insertion sort
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭