排序之合并排序
题目:
给一个数组进行从小到大进行排序。
思路:
归并排序:
1、两个有序数组进行归并,复杂度为O(n)。那么就可采用分治,用logn次O(n)进行排序。
2、设置排序区间大小s,s从1开始直到len/2。
3、开一个和原数组一样大的数组作为辅助数组b,每次从a归并到b再从b归并到a。
void Mergesort(int a[],int r)
{
int s=1;
while(s<r)
{
Mergepass(a,b,s,r);
s+=s;
Mergepass(b,a,s,r);
s+=s;
}
}
4、进行分块,每个块大小为2*s,块内进行归并排序。
5、当剩余一部分不够分的时候,进行分类讨论,如果剩下的元素能分为两组,但是第二组较少,仍可以进行归并,但是如果剩下的元素不够分成两组的话,直接把剩下的元素复制到目标数组就可以了,因为单位区间内是有序的。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N], b[N];
void Merge(int a[], int b[], int l, int mid, int r)
{
int i = l, j = mid + 1, cnt = l;
while (i <= mid && j <= r)
{
if (a[i] <= a[j])
b[cnt++] = a[i++];
else
b[cnt++] = a[j++];
}
for (int p = i; p <= mid; ++p)
b[cnt++] = a[p];
for (int q = j; q <= r; ++q)
b[cnt++] = a[q];
}
void Merge_pass(int a[], int b[], int s, int l, int r)
{
int i;
for (i = l; i < r - 2 * s + 1; i += 2 * s)
Merge(a, b, i, i + s - 1, i + 2 * s - 1);
if (i + s - 1 < r)
Merge(a, b, i, i + s - 1, r - 1);
else
for (int j = i; j < r; ++j)
b[j] = a[j];
}
void Merge_sort(int l, int r)
{
int s = 1;
while (s < r - l)
{
Merge_pass(a, b, s, l, r);
s += s;
Merge_pass(b, a, s, l, r);
s += s;
}
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; ++i)
cin >> a[i];
Merge_sort(0, n);
for (int i = 0; i < n; ++i)
{
cout << a[i];
if (i != n - 1)
cout << ' ';
}
cout << endl;
return 0;
}