归并排序思想遵循分治法
在实现上有三个操作:
分解,将待排序的n个元素的序列分解成两个n/2元素的子序列;
解决,使用归并排序递归排序子序列;
合并,合并两个已排序的子序列。
归并排序算法的关键操作是合并步骤中两个已排序序列的合并。
伪代码表示
其中A是数组,p、q、r是数组下标,满足p<=q
//合并
MERGE(A, p, q, r) n1 = q - p + 1 n2 = r - q let L[1..n1 + 1] and R[1..n2 + 1] be new arrays for i = 1 to n1 L[i] = A[p + i - 1] for j = 1 to n2 R[j] = A[q + j] L[n1 + 1] = ∞ R[n2 + 1] = ∞ i = 1 j = 1 for k = p to r if L[i] <= R[j] A[k] = L[i] i = i + 1 else A[k] = R[j] j = j + 1 //排序算法(q向下取整) MERGE-SORT(A, p, r) if p < r q = (p + r) / 2 MERGE-SORT(A, p, q) MERGE-SORT(A, q + 1, r) MERGE(A, p, q, r)
Java代码表示
public static void merge(int[] queue, int p, int q, int r) {
int i = p, j = q, m = q + 1, n = r, k = 0;
int temp[] = new int[r - p + 1];
while (i <= j && m <= n) {
if (queue[i] < queue[m]) {
temp[k++] = queue[i++];
} else {
temp[k++] = queue[m++];
}
}
while (i <= j) {
temp[k++] = queue[i++];
}
while (m <= n) {
temp[k++] = queue[m++];
}
System.arraycopy(temp, 0, queue, p, temp.length);
}
public static void mergeSort(int[] queue, int p, int r) {
if (p > r) {
int q = (p + r) / 2;
mergeSort(queue, p, q);
mergeSort(queue, q + 1, r);
// 合并两个有序序列
merge(queue, p, q, r);
}
}
排序过程大致为:
归并排序的时空复杂度
1、设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。
2、因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。
3、归并的空间复杂度就是那个临时的数组和递归时压入栈的数据占用的空间:n + logn;所以空间复杂度为: O(n)。
以上,就是笔者对于归并排序的初略见解。