Problem Description
归并排序是基于归并操作完成的,而一次归并操作是通过两个或两个以上的有序表合并成一个新的有序表完成的。常见的归并排序是2-路归并排序,其核心操作是将一维数组中前后相邻的两个有序序列归并成一个有序序列。其算法可以描述如下:
在本题中,读入一串整数,将其使用以上描述的2-路归并排序的方法从小到大排序,并输出。
Input Description
输入的第一行包含1个正整数n,表示共有n个整数需要参与排序。其中n不超过100000。
第二行包含n个用空格隔开的正整数,表示n个需要排序的整数。
Output Description
只有1行,包含n个整数,表示从小到大排序完毕的所有整数。
请在每个整数后输出一个空格,并请注意行尾输出换行。
Sample Input
10
2 8 4 6 1 10 7 3 5 9
Sample Output
1 2 3 4 5 6 7 8 9 10
Hint
在本题中,需要按照题目描述中的算法完成2-路归并排序的算法。
不难发现,2-路归并算法的时间复杂度为O(nlog2n),且需要和原始数据等数量的辅助空间。递归形式的2-路归并排序算法在形式上比较简洁,但是实用性较差。通常在需要使用归并排序的场合,往往使用非递归形式的归并排序。
与快速排序和堆排序相比,归并排序的特点在于其是一种稳定的排序方法。
我的想法:
我的代码:
#include <iostream>
using namespace std;
typedef struct SqList
{
int str[100000];
int length;
}SqList;
int n;
void CreateList(SqList &S, int n)
{
//S.str = new int[n + 1];
S.length = n;
for (int i = 1; i <= S.length; i++)
{
cin >> S.str[i];
}
}
void Merge(int SR[], int TR[], int i, int m, int n)
{
int j, k;
for (j = m + 1, k = i; i <= m && j <= n; ++k)
{
if (SR[i] <= SR[j])
{
TR[k] = SR[i++];
}
else
{
TR[k] = SR[j++];
}
}
if (i <= m)
{
while (k <= n && i <= m)
{
TR[k++] = SR[i++];
}
}
if (j <= n)
{
while (k <= n && j <= n)
{
TR[k++] = SR[j++];
}
}
}
void MSort(int SR[], int TR1[], int s, int t)
{//将SR[s..t]归并排序为TR1[s..t]
int m;
int TR2[100000];
if (s == t)//表示只有一个元素
{
TR1[t] = SR[s];
}
else
{
m = (s + t) / 2;//将SR[s..t]平分成SR[s..m]和SR[m+1..t]
MSort(SR, TR2, s, m);//
MSort(SR, TR2, m + 1, t);
Merge(TR2, TR1, s, m, t);
}
}
void MergeSort(SqList &L)
{
MSort(L.str, L.str, 1, L.length);
}
void Print(SqList S)
{
for (int i = 1; i <= S.length; i++)
{
cout << S.str[i] << " ";
}
cout << endl;
}
int main()
{
SqList S;
scanf("%d", &n);
if (n > 100000)
{
return 0;
}
CreateList(S, n);
MergeSort(S);
Print(S);
return 0;
}