归并排序
思路
1.分解:分解待排序的\(n\)个元素的序列成各具\(n/2\)个元素的俩哥哥子序列
2.解决:使用归并排序递归的排序两个子序列
3.合并:合并两个已排序的子序列得到答案
合并
先考虑将两个已排序好的数组合并为一个数组
伪代码如下:
MERGE(A, p, q, r) //合并数组A[p..q],A[q+1..r] n1 = q - p + 1 n2 = r - q let L[1..n1+1] and R[1..n2+1] be new array for i = 1 to n1 L[i] = A[p+i-1] for j = 1 to n2 R[j] = A[q+j-1] L[n1+1] = INFINITY //设置哨兵元素 R[n2+1] = INFINITY //设置哨兵元素 i = 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
解决
将MERGE作为归并排序的一个子程序调用,下面的过程MERGE_SORT,排序子数组$A[p..r] $中的元素。若 $p \geq r $, 则该子数组最多有一个元素,则已经排好序,否则,分解步骤简单的计算一个下标 \(q\) ,将 \(A[p, r]\) 分成两个子数组\(A[p, q]\) 和 \(A[q+1, r]\) ,前者包含\(\lceil n/2 \rceil\)个元素,后者包含\(\lfloor n / 2 \rfloor\)个元素
伪代码如下:
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)
实现代码
#include <bits/stdc++.h> void Merge(int A[], int p, int q, int r) { int n1, n2, i, j, k; n1 = q - p + 1; n2 = r - q; int L[n1+1], R[n2+1]; for(i = 0; i < n1; i++) { L[i] = A[p+i]; } for(j = 0; j < n2; j++) { R[j] = A[q+1+j]; } L[n1] = 100000007; R[n2] = 100000007; i = j = 0; for(k = p; k <= r; k++) { if(L[i] <= R[j]) { A[k] = L[i]; i++; } else{ A[k] = R[j]; j++; } } } void Merge_sort(int A[], int p, int r){ if(p < r) { int q = (p + r) / 2; Merge_sort(A, p, q); Merge_sort(A, q+1, r); Merge(A, p, q, r); } } int main(){ int A[10] = {0, 5, 7, 6, 485, 48, 15, 49, 83, 464}; Merge_sort(A, 0, 9); int i; for(i = 0; i < 10; i++) { printf("%d ", A[i]); } }