归并排序
顾名思义,先分后合,利用分治思想:
1、先分解待排序的n个元素序列形成n/2个元素的两个子序列。
2、然后使用归并排序递归排序两个子序列。
3、最后合并两个已经排序的子序列以产生已排序的答案。
分析:
分解:分解仅仅计算子数组的中间位置,需要常量时间,D(n) = Θ(1)。
解决:递归解两个规模为n/2的子问题,2T(n/2)的运行时间。
合并:在一个n个元素的子数组上 MERGE需要Θ(n),所以C(n)=Θ(n)。
T(n) = Θ(1) 若n = 1
2T(n/2) + Θ(n) 若n > 1
即:
T(n) = c 若n = 1
2T(n/2) +cn 若n > 1
时间复杂度最好情况:O(n log n) ,最坏情况:O(n log n) ,平均情况:O(n log n)
伪代码:
MERGE(A, p, q, r)
n1 = q - p + 1
n2 = r - q
create arrays L[n1 + 1] and R[n2 + 1]
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 = 0
j = 0
for k = p to r
if L[i] <= R[j]
A[k] = L[i]
if L[i] > R[j]
A[k] = R[j]
Java代码:
public class MergeSort {
public static void main(String[] args) {
int []a = {2,4,5,7,1,2,3,6};
merge_Sort(a, 0, a.length-1);
for(int i = 0 ; i < a.length ; i++) {
System.out.print(a[i] + " ");
}
}
public static void merge_Sort(int []a, int p, int r) {
if(p < r) {
int q = (int)Math.floor(( p + r ) / 2);
merge_Sort(a, p, q);
merge_Sort(a, q + 1, r);
merge(a, p, q, r);
}
}
public static void merge(int []a, int p, int q, int r) {
int n1 = q - p + 1;
int n2 = r - q;
int []L = new int[n1 + 1];
int []R = new int[n2 + 1];
for(int i = 0; i < n1 ; i++) {
L[i] = a[p + i];
}
for(int j = 0; j < n2 ; j++) {
R[j] = a[q + j + 1];
}
L[n1] = 1000000;
R[n2] = 1000000;
int i1 = 0;
int j1 = 0;
for(int k = p ; k <= r ; k++) {
if(L[i1] <= R[j1] ){
a[k] = L[i1];
i1++;
}
else {
a[k] = R[j1];
j1++;
}
}
}
}