//分治的典型应用————归并排序
/*
数组排序任务可以如下完成:
1) 把前一半排序
2) 把后一半排序
3) 把两半归并到一个新的有序数组,然后再拷贝回原 数组,排序完成。
归并排序的时间复杂度
对n个元素进行排序的时间:
T(n) = 2*T(n/2) + a*n (a是常数,具体多少不重要)
= 2*(2*T(n/4)+a*n/2)+a*n
= 4*T(n/4)+2a*n
= 4*(2*T(n/8)+a*n/4)+2*a*n
= 8*T(n/8)+3*a*n
...
= 2k *T(n/2k)+k*a*n
一直做到 n/2k = 1 (此时 k = log2n),
T(n) = 2k *T(1)+k*a*n
= 2k *T(1)+k*a*n
= 2k+k*a*n
= n+a*(log2n)*n
复杂度O(nlogn)
*/
#include <iostream>
using namespace std;
void Merge(int a[],int s,int m, int e,int tmp[]) //将两个数组进行合并
{ //将数组a的局部a[s,m]和a[m+1,e]合并到tmp,并保证tmp有序,然后再拷贝回a[s,m]
//归并操作时间复杂度:O(e-m+1),即O(n)
int pb = 0; //指向tmp[]数组
int p1 = s,p2 = m+1; //分别指向两个待归并数组的首部
while( p1 <= m && p2 <= e) //保证都没有越界
{
if( a[p1] < a[p2])
tmp[pb++] = a[p1++];
else
tmp[pb++] = a[p2++];
}
while( p1 <= m) //若第一个数组还有元素
tmp[pb++] = a[p1++];
while( p2 <= e) //若第二个数组还有元素
tmp[pb++] = a[p2++];
for(int i = 0;i < e-s+1; ++i) //核心:需拷贝回的元素个数
a[s+i] = tmp[i];
}
void MergeSort(int a[],int s,int e,int tmp[]) //归并排序
{
if( s < e) //大条件
{
int m = s + (e-s)/2; //有效的避免了数据溢出问题
MergeSort(a,s,m,tmp);//对前一半进行归并排序
MergeSort(a,m+1,e,tmp);//对后一半进行归并排序
Merge(a,s,m,e,tmp); //将这两半合并起来
}
}
int a[10000]; //待排数组
int b[10000]; //归并排序需要一个与待排数组等大的辅助空间
int main()
{
int n;
cin >> n;
for(int i = 0; i<n ;i++)
cin >> a[i];
// int size = sizeof(a)/sizeof(int); //获取数组 a 中元素的个数
MergeSort(a,0,n-1,b); //进行归并排序
for(int i = 0;i < n; ++i) //输出
cout << a[i] << ",";
cout << endl;
return 0;
}