问题

使用归并排序如下数组 [32, 12, 43, 5, 3, 8],使得排序后的结果为:
[3, 5, 8, 12, 32, 43]

思路

解题需要以下两个知识:

1、归并排序的核心思想是分治思想,就是把需要排序的规模分到最小,本题中是要分到什么程度呢,也就是说分到每个数组里面只有一个元素,一个元素也就不用排了,就是这个元素本身

2、合并 两个有序的数组合并成一个有序的数组,这也就是这个归并排序名称的由来,具体归并的操作如下两个有序数组 a1=[1,3,5]和a2=[2,4,6] 合并之后是33=[1,2,3,4,5,6]。这里面主要用到两个指针,一个指向A1的开头p1,一个指向A2的开头p2,和一个空数组A3。然后比较a1[p1]和a2[p2]的大小,把小的放入到a3中,然后小的指针继续往下走,直到其中的一个数组的元素都走完,然后把另外一个数组的元素剩余的部分全部放入到a3结尾处。图例如下:归并排序java实现-LMLPHP

编码

 /**
   * 归并排序
   * @param a 待排序的数组
   */
  public void mergeSort(int[] a) {
    int[] temp = new int[a.length];
    mergeSortSub(a, temp, 0, a.length - 1);
  }

  /**
   * 需要用分治的代码,其中left<right是跳出循环的条件。
   * 分治之后调用merge函数对数组进行合并
   * @param a 待排序的数组
   * @param temp 临时用来存放数组的数组
   * @param left 分治以后的数组的左边界
   * @param right 分治之后数组的右边界
   */
  public void mergeSortSub(int[] a, int[] temp, int left, int right) {
    if (left < right) {
      int center = (left + right) / 2;
      mergeSortSub(a, temp, left, center);
      mergeSortSub(a, temp, center + 1, right);
      merge(a, temp, left, center + 1, right);
    }
  }


  /**
   * 一个数组从中间分为两个有序数组,合并这两个有序数组
   *
   * @param a        待排序和合并的数组
   * @param temp     合并和排序的结果
   * @param leftPos  左边有序数组起点
   * @param rightPos 右边有序数组的起点
   * @param rightEnd 右边的终点
   */
  public void merge(int[] a, int[] temp, int leftPos, int rightPos, int rightEnd) {

    int leftEnd = rightPos - 1;
    int tempPos = leftPos;
    int numElements = rightEnd - leftPos + 1;

    while (leftPos <= leftEnd && rightPos <= rightEnd) {
      int leftValue = a[leftPos];
      int rightValue = a[rightPos];
      if (leftValue > rightValue) {
        temp[tempPos] = rightValue;
        rightPos++;
      } else {
        temp[tempPos] = leftValue;
        leftPos++;
      }
      tempPos++;
    }
    while (leftPos <= leftEnd) {
      temp[tempPos] = a[leftPos];
      leftPos++;
      tempPos++;
    }
    while (rightPos <= rightEnd) {
      temp[tempPos] = a[rightPos];
      rightPos++;
      tempPos++;
    }
    for (int i = 0; i < numElements; i++, rightEnd--) {
      a[rightEnd] = temp[rightEnd];
    }
  }
//测试代码
 @Test
  public void test_mergeSort() {
  	int[] array = new int[]{32, 12, 43, 5, 3, 8};
    int[] after = new int[]{3, 5, 8, 12, 32, 43};
    mergeSort(array);
    Assert.assertArrayEquals(after, array);
  }

其中代码的执行流程如下图:归并排序java实现-LMLPHP

时间复杂度

O(NlogN)

以上就是java实现归并排序的全过程。最后再强调一遍,归并排序的两个关键点 分治合并有序数组

05-12 12:23