归并排序

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。

时间复杂度:最好时间复杂度很最坏时间复杂度都是归并排序 - 图1#card=math&code=O%28N%20%5Clog%20N%29)。

归并排序的思想并不能理解,下面我们通过一个例子直观的看一下归并排序中”分”和”归”的具体过程。假设现在待排序数组为归并排序 - 图2

归并排序.png

分的过程就是不断的进行分解,直到数组元素只有一个。接下来具体看一下最后一次归并的具体过程,设置两个指针left和right分别指向两个待归并子数组的起始位置,并申请临时数组保存此轮归并的结果;当排序结束后将临时数组元素逐个复制到原始数组即可。了解了归并排序的整体流程后,下面给出实现代码:

  1. // Java实现
  2. public class MergeSort {
  3. public static void mergeSort(int[] arr) {
  4. if (arr == null || arr.length < 2) {
  5. return;
  6. }
  7. mergeSort(arr, 0, arr.length - 1);
  8. }
  9. public static void mergeSort(int[] arr, int l, int r) {
  10. // 递归出口,当只有一个元素时返回
  11. if (l == r) {
  12. return;
  13. }
  14. int mid = l + ((r - l) >> 1);
  15. // 左半个数组排序
  16. mergeSort(arr, l, mid);
  17. // 右半个数组排序
  18. mergeSort(arr, mid + 1, r);
  19. // 归并有序数组
  20. merge(arr, l, mid, r);
  21. }
  22. // 归并过程
  23. // 申请额外的数组,设置两个指针分别指向两个子数组的起始位置
  24. // 选择两个指针指向的较小元素放入数组,更新指针,直到一个数组访问结束
  25. // 最后将剩下的元素直接放入额外数组的后面即可
  26. public static void merge(int[] arr, int l, int m, int r) {
  27. int[] help = new int[r - l + 1];
  28. int i = 0;
  29. int p1 = l;
  30. int p2 = m + 1;
  31. while (p1 <= m && p2 <= r) {
  32. help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
  33. }
  34. while (p1 <= m) {
  35. help[i++] = arr[p1++];
  36. }
  37. while (p2 <= r) {
  38. help[i++] = arr[p2++];
  39. }
  40. // 最后将额外数组中元素复制到原数组中
  41. for (i = 0; i < help.length; i++) {
  42. arr[l + i] = help[i];
  43. }
  44. }

下面是Python的简单实现:

  1. class MergeSort:
  2. def __init__(self, arr):
  3. self.arr = arr
  4. def sort(self):
  5. if len(self.arr) < 2: return
  6. self.mergeSort(self.arr, 0, len(self.arr) - 1)
  7. print(self.arr)
  8. def mergeSort(self, arr, left, right):
  9. if left == right: return
  10. middle = left + ((right - left) // 2)
  11. self.mergeSort(arr, left, middle)
  12. self.mergeSort(arr, middle + 1, right)
  13. self.merge(arr, left, middle, right)
  14. def merge(self, arr, left, middle, right):
  15. array = []
  16. p, q = left, middle + 1
  17. while p <= middle and q <= right:
  18. if arr[p] < arr[q]:
  19. array.append(arr[p])
  20. p += 1
  21. else:
  22. array.append(arr[q])
  23. q += 1
  24. while p <= middle:
  25. array.append(arr[p])
  26. p += 1
  27. while q <= right:
  28. array.append(arr[q])
  29. q += 1
  30. for i in range(len(array)):
  31. self.arr[left + i] = array[i]
  32. if __name__ == "__main__":
  33. a = [1,8,6,5,7,3]
  34. MergeSort(a).sort()