这里的归并和通常写的不一样。通常写的归并是对半的,即像如下形式:
vector<int> mergeSort(vector<int> & arr, int left, int right){
// [l, r)
if(left >= right)
return {};
auto mid = (left + right) / 2;
l = mergeSort(left, mid);
r = mergeSort(mid,right);
return mergeTwo(l, r);
}
但本题的归并是每两个、每四个、每八个…有序数组这样合并的。
#include<bits/stdc++.h>
using namespace std;
vector<int> partial;
int n;
bool isMerge = false;
ostream& operator <<(ostream& os, vector<int> & arr) {
int len = arr.size();
for(int i = 0; i < len; ++i) {
os << arr[i];
if(i != len - 1)
os << " ";
}
return os;
}
bool mergeTwo(vector<int> & arr, int l1, int l2, int r2) {
int r1 = l2;
int i = l1, j = l2;
vector<int> tmp(r2 - l1);
int cur = 0;
while(i < r1 && j < r2) {
if(arr[i] < arr[j])
tmp[cur++] = arr[i++];
else
tmp[cur++] = arr[j++];
}
while(i < r1)
tmp[cur++] = arr[i++];
while(j < r2)
tmp[cur++] = arr[j++];
for(int k=0; k < r2 - l1; ++k)
arr[k + l1] = tmp[k];
return false;
}
void
checkMerge(vector<int> & arr, int left, int right, int span) {
if(span >= n)
return;
int prev_end = left, cnt = 0;
while(prev_end < right) {
cnt++;
if(cnt % 2 == 0)
mergeTwo(arr, prev_end - span, prev_end, min(prev_end + span, right));
prev_end += span;
}
if(isMerge) {
cout << "Merge Sort" << endl;
cout << arr << endl;
return;
}
if(arr == partial)
isMerge = true;
checkMerge(arr, left, right, span * 2);
}
void insertSort(vector<int> & arr) {
int pivot = -1;
for(int i = 1; i < n; ++i) {
if(arr[i] < arr[i-1]) {
pivot = i;
break;
}
}
if(pivot != -1) {
int val = arr[pivot];
auto iter = lower_bound(arr.begin(), arr.begin() + pivot,
arr[pivot]);
arr.erase(arr.begin() + pivot);
arr.insert(iter, val);
} else {
if(arr[0] > arr[1])
swap(arr[0], arr[1]);
}
cout << "Insertion Sort" << endl;
cout << arr << endl;
}
int main() {
scanf("%d", &n);
vector<int> ori(n);
partial.resize(n);
for(int i = 0; i < n; ++i)
scanf("%d", &ori[i]);
for(int i = 0; i < n; ++i)
scanf("%d", &partial[i]);
vector<int> arr(ori);
checkMerge(arr, 0, n, 1);
if(! isMerge) {
insertSort(partial);
}
}