归并排序 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(   "]" );
      }

}











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值