归并排序有递归写法和非递归写法,但是由于栈内存的开销以及时间的消耗,往往使用非递归的算法。归并排序顾明思议是将几个有序的序列归并到一个序列,使用的merge函数是采用two pointer的方法。
题目中如果要模拟归并排序,自己去写merge函数就太耗时了,如果只是要模拟过程,可以用STL 中的sort函数替换merge(当然,时间消耗会多一点)。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
//freopen("1.txt", "r", stdin);
int n; cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
//由于最后一段可能不能不够step,所以条件判断是step/2<n而不是step<n
//条件判断中取不取等都可以
for (int step = 2; step / 2 < n; step *= 2) {
for (int i = 0; i < n; i += step)
sort(a.begin() + i, a.begin() + min(i + step, n)); //借用快排
//min(i+step,n)用于最后一段,不过最后一段也可以单独求
}
for (int i = 0; i < n; i++) {
cout << a[i];
if (i != n - 1) cout << " ";
}
return 0;
}
1089 Insert or Merge (25分)
题目大意
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法是插入算法还是归并算法。首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列
分析
根据插入排序和归并排序的特点,插入排序前一部分有序,后一部分和原序列相同。一旦排除插入排序,则是归并排序,对原始序列模拟归并排序,当和中间序列相同时再进行一次归并几位所求结果。
注意:序列中可能存在相等的数。
AC代码
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
//freopen("1.txt", "r", stdin);
int n; cin >> n;
int *a = new int[n];
int *b = new int[n];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cin >> b[i];
}
int k, j;
for (k = 0; k < n - 1 && b[k] <= b[k + 1]; k++); //k是最后一个满足升序的位置
for (j = k + 1; j < n&&a[j] == b[j]; j++);
if (j == n) {
printf("Insertion Sort\n");
sort(a, a + k + 2);
}
else {
printf("Merge Sort\n");
int step = 2, flag = 1;
while (flag) {
flag = 0;
for (int i = 0; i < n; i++) {
if (a[i] != b[i]) flag = 1;
}
int i;
for (i = 0; i < n; i += step) {
sort(a + i, a + min(i + step, n));
}
step *= 2;
}
}
for (int i = 0; i < n; i++) {
cout << a[i];
if (i != n - 1) cout << " ";
}
delete[] a;
delete[] b;
return 0;
}