归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
时间复杂度:最好时间复杂度很最坏时间复杂度都是#card=math&code=O%28N%20%5Clog%20N%29)。
归并排序的思想并不能理解,下面我们通过一个例子直观的看一下归并排序中”分”和”归”的具体过程。假设现在待排序数组为:

分的过程就是不断的进行分解,直到数组元素只有一个。接下来具体看一下最后一次归并的具体过程,设置两个指针left和right分别指向两个待归并子数组的起始位置,并申请临时数组保存此轮归并的结果;当排序结束后将临时数组元素逐个复制到原始数组即可。了解了归并排序的整体流程后,下面给出实现代码:
// Java实现public class MergeSort {public static void mergeSort(int[] arr) {if (arr == null || arr.length < 2) {return;}mergeSort(arr, 0, arr.length - 1);}public static void mergeSort(int[] arr, int l, int r) {// 递归出口,当只有一个元素时返回if (l == r) {return;}int mid = l + ((r - l) >> 1);// 左半个数组排序mergeSort(arr, l, mid);// 右半个数组排序mergeSort(arr, mid + 1, r);// 归并有序数组merge(arr, l, mid, r);}// 归并过程// 申请额外的数组,设置两个指针分别指向两个子数组的起始位置// 选择两个指针指向的较小元素放入数组,更新指针,直到一个数组访问结束// 最后将剩下的元素直接放入额外数组的后面即可public static void merge(int[] arr, int l, int m, int r) {int[] help = new int[r - l + 1];int i = 0;int p1 = l;int p2 = m + 1;while (p1 <= m && p2 <= r) {help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];}while (p1 <= m) {help[i++] = arr[p1++];}while (p2 <= r) {help[i++] = arr[p2++];}// 最后将额外数组中元素复制到原数组中for (i = 0; i < help.length; i++) {arr[l + i] = help[i];}}
下面是Python的简单实现:
class MergeSort:def __init__(self, arr):self.arr = arrdef sort(self):if len(self.arr) < 2: returnself.mergeSort(self.arr, 0, len(self.arr) - 1)print(self.arr)def mergeSort(self, arr, left, right):if left == right: returnmiddle = left + ((right - left) // 2)self.mergeSort(arr, left, middle)self.mergeSort(arr, middle + 1, right)self.merge(arr, left, middle, right)def merge(self, arr, left, middle, right):array = []p, q = left, middle + 1while p <= middle and q <= right:if arr[p] < arr[q]:array.append(arr[p])p += 1else:array.append(arr[q])q += 1while p <= middle:array.append(arr[p])p += 1while q <= right:array.append(arr[q])q += 1for i in range(len(array)):self.arr[left + i] = array[i]if __name__ == "__main__":a = [1,8,6,5,7,3]MergeSort(a).sort()
