归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并排序是一种稳定的排序方法。
时间复杂度:最好时间复杂度很最坏时间复杂度都是 O ( N log N ) O(N \log N) O(NlogN)。
归并排序的思想并不能理解,下面我们通过一个例子直观的看一下归并排序中"分"和"归"的具体过程。假设现在待排序数组为 [ 1 , 8 , 2 , 5 , 7 , 3 ] [1,8,2,5,7,3] [1,8,2,5,7,3],归并排序的整体过程如下所示:
分的过程就是不断的进行分解,直到数组元素只有一个。接下来具体看一下最后一次归并的具体过程,设置两个指针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 = arr
def sort(self):
if len(self.arr) < 2: return
self.mergeSort(self.arr, 0, len(self.arr) - 1)
print(self.arr)
def mergeSort(self, arr, left, right):
if left == right: return
middle = 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 + 1
while p <= middle and q <= right:
if arr[p] < arr[q]:
array.append(arr[p])
p += 1
else:
array.append(arr[q])
q += 1
while p <= middle:
array.append(arr[p])
p += 1
while q <= right:
array.append(arr[q])
q += 1
for i in range(len(array)):
self.arr[left + i] = array[i]
if __name__ == "__main__":
a = [1,8,6,5,7,3]
MergeSort(a).sort()