排序 - 归并排序 [2]


我们知道归并排序是拆分和合并两部分。

说完了归并排序的 拆分部分

继续说说合并部分。

 

还是先回顾下拆分吧。

随便说个数组 { 9, 2, 7, 1, 3, 6, 5, 4}

拆分过程:
   9,  2, 7, 1          3, 6, 5,4

 9, 2      7,1       3, 6     5, 4          

9  2     7   1       3   6     5   4 

 

好,到此我们对原数组完成了拆分,如果你不了解拆分,请一定看我的上一篇来弄懂拆分是如何工作的。

 

上面的拆分结果是最终的结果,其实合并是穿插在拆分过程中的。

 

当 9,2,7,1  --> 9,2 --> 9 & 2 的时候,9是某次递归中的左半部分,而2是这次递归中的右半部分。

当左半部分和右半部分都完成拆分的时候,我们就需要对他进行合并。

 

合并规则:

1. 创建一个数组,数组长度等于待合并左半部分和右半部分的数组元素总和;

2. 比较左面数组和右面数组中的第一个元素,选其较小者放入数组的第一个元素位置;

    2.5. 如果左面数组和右面数组都只有一个元素,那么此时我们已经处理了其中一个,对上例来讲,我们已经把 右面数组的唯一元素:2 放入了数组中,那么就只剩下左面元素:9;再将9直接追加到新数组的后面即可;

3. 综合2和2.5,我们知道合并是这样进行的:总是选择两边较小的元素追加到新元素的下一个元素的位置;

4. 当其中一部分(左面部分或右面部分)处理完成后,将另一部分的所有元素直接追加到新数组的后面,如此完成合并。

 

合并过程如下:

9  2    7   1     3  6     5  4

2,9     1,7        3,6      4,5

1,2,7,9            3,4,5,6

1,2,3,4,5,6,7,9

 

我在上一篇中提到一个问题:

拆分的结果就是每个元素都被拆分为一个单元,那干脆直接将每个元素都当做一个单元来处理不就得了,干嘛还做什么拆分?

原因在合并过程中就体现出来了。

 

1. 细心点,你会发现每次合并的左右两半部分数组都是 有序 的,只有有序,才能用上面的合并的规则;

2. 拆分和合并是一个递归过程,递归,还是递归,还要花些时间理解。

 

这篇写的不好。心不在焉。。如果你看到觉得不明白,欢迎讨论。

package r;
 
public class MyMergeSort {
 
 public static int[] array = {19, 1,90, 22, 11, 12, 9, 3};
 
 public static void mergeSort(int[] sortArr, int start, int end) {
    int len = end - start;
    if (len < 1) return;
    else {
      int mid = start + len / 2;
      printArr(sortArr, start, mid);
      printArr(sortArr, mid + 1, end);
     
     System.out.println("======================");
      mergeSort(sortArr, start, mid);
      mergeSort(sortArr, mid + 1, end);
     
      merge(sortArr, start, mid, mid+1, end);
     
      System.out.println("*************PRINT *********");
      printArr(sortArr, start, end);
    }
 }
 
 private static void merge(int[] sortArr, int leftStart, int leftEnd, intrightStart, int rightEnd) {
    int leftPointer = leftStart;
    int rightPointer = rightStart;
   
    int[] sortedArr = new int[rightEnd -leftStart + 1];
    int index = -1;
    while (leftPointer <= leftEnd &&rightPointer <= rightEnd) {
      index++;
      int s = getSmaller(sortArr, leftPointer,rightPointer);
      sortedArr[index] = sortArr[s];
     
      if (s == leftPointer) leftPointer++;
      else rightPointer++;
    }
   
    if (leftPointer <= leftEnd) {
      for (int i = leftPointer; i <=leftEnd; i++) {
        sortedArr[++index] = sortArr[i];
      }
    }
   
    if (rightPointer <= rightEnd) {
      for (int i = rightPointer; i <=rightEnd; i++) {
        sortedArr[++index] = sortArr[i];
      }
   }
   
    // Copy back
    for (int i = 0; i < sortedArr.length;i++) {
      sortArr[leftStart + i] = sortedArr[i];
    }
 }
 
 private static int getSmaller(int[] sortArr, int leftPointer, intrightPointer) {
    if (sortArr[leftPointer] <sortArr[rightPointer])
      return leftPointer;
    else
      return rightPointer;
 }
 
 private  static voidprintArr(int[] arr, int start, int end) {
    for (int i = start; i <= end; i++) {
      System.out.print(arr[i] + "  ");
    }
    System.out.println("\r\n--------");
 }
 
 
 public static void main(String[] args) {
    mergeSort(array, 0, array.length - 1);
   
//    printArr(array, 0, array.length - 1);
 }
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值