归并排序的基本思想,就是采用分治的策略。先使子序列都有序,然后再将子序列归并成一个有序的序列。
例如:一个原始序列为:
(9,2,3,1,6,4,5,8,9,7)
分成
(9,2,3,1,6) (4,5,8,9,7)
(9,2,3)(1,6) (4,5,8)(9,7)
(9,2)(3) (1)(6) (4,5)(8) (9)(7)
(9)(2)(3)(1)(6) (4)(5)(8)(9)(7)
然后“治”,递归地进行合并操作
(2,9)(1,3)(6) (4,5)(8,9)(7)
(1,2,3,9)(6) (4,5,8,9)(7)
(1,2,3,6,9) (4,5,7,8,9)
(1,2,3,4,5,6,7,8,9,9)
最后合并成一个有序的数列。
归并排序是稳定的排序,归并排序的平均最好和最坏时间复杂度都是O(N*lgN),空间复杂度为O(N)
参考代码(递归):
void Merge(int a[], int l , int m, int r)
{
int temp[100];
int i = l;
int j = m+1;
int n = 0;
while (i <= m && j <=r)
{
if(a[i]<=a[j])
{
temp[n++] = a[i++];
}
else{
temp[n++] = a[j++];
}
}
while (i <= m)
{
temp[n++] = a[i++];
}
while (j <= r)
{
temp[n++] = a[j++];
}
n = 0;
while (l <= r)
{
a[l++] = temp[n++];
}
}
void MergeSort(int a[], int l, int r)
{
if(l < r)
{
int m = (l+r)/2;
MergeSort(a, l, m);
MergeSort(a, m+1, r);
Merge(a, l, m , r);
}
}
非递归的方式,就是自底向上
(9,2,3,1,6,4,5,8,9,7)
(9,2)(3,1)(6,4)(5,8)(9,7)
(2,9)(1,3)(4,6)(5,8)(7,9)
(1,2,3,9)(4,5,6,8)(7,9)
(1,2,3,4,5,6,8,9)(7,9)
(1,2,3,4,5,6,7,8,9,9)
void non_recursionMergeSort(int a[], int n)
{
int temp[100];
int t = 1;
while (t <= n)
{
for(int i = 0; i + t <= n; i += t * 2)
{
int l = i, m = i + t - 1, r = i + 2 * t - 1;
if (r > n-1)
{
r = n-1;
}
Merge(a, l, m, r);
}
t *=2;
}
}
---------------------------------------------------
n个有序数组合并,就是用了归并的思想。