归并排序完全遵循分治模式,直观上操作可分为:
分解:分解待排序的n个元素的序列各具有n/2个元素的两个子序列。
解决:使用归并排序递归的排序两个子序列。
合并:合并两个已排好序的子序列以产生已排序的答案。
当递归到序列长度为1时,递归回升,此时不需要做任何操作,因为长度为1的每个序列都已排好序。
归并算法的关键操作是"合并"步骤中两个已排序序列的合并。我们通过Merge(A, p, q, r)来完成合并,其中A是一个数组,p、q、和 r是一个数组的下标,满足p<=q<r。该过程假设子数组A[p..q],和A[q+1...r]都已排
好序。它合并这两个子数组形成单一的已排好序的数组并代替当前的子数组A[p...r]。
时间复杂度 O(n*log(n)),【空间复杂度O(n),】稳定排序。
伪代码:
Merge (A, p, q, r) n1 = p - q + 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] = inf R[n2 + 1] = inf i = 1 j = 1 for k = p to r if L[i] <= R[j] A[k++] = L[i] i++ else A[k++] = R[j] j++ MergeSort(A, p, r) if p < r q = int((p + r)/2) MergeSort(A, p, q) MergeSort(A, q+1, r) Merge(A, p, q, r)
示例代码:
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; int num[1010], temp[1010]; void Merge(int A[], int p, int q, int r) { int i = p; int j = q + 1; int k = 0; while(i <= q && j <= r) { if (A[i] < A[j]) temp[k++] = A[i++]; else temp[k++] = A[j++]; } while(i <= q) { temp[k++] = A[i++]; } while(j <= r) { temp[k++] = A[j++]; } for (int i=0; i<k; ++i) { A[p+i] = temp[i]; } } void MergeSort(int A[], int p, int r) { int q; if (p < r) { q = (p + r) / 2; MergeSort(A, p, q); MergeSort(A, q+1, r); Merge(A, p, q, r); } } int main() { freopen("1.in.cpp", "r", stdin); int n; while(~scanf("%d", &n)) { for (int i=0; i<n; ++i) { scanf("%d", &num[i]); } MergeSort(num, 0, n-1); for (int i=0; i<n; ++i) { printf("%d ", num[i]); } printf(" "); } return 0; }