PAT甲级 1089 Insert or Merge(25)

该程序实现了一种非典型的归并排序方法,不是通常的对半合并,而是每两个、四个、八个等有序数组进行合并。在无法直接使用常规归并排序时,会转而使用插入排序。程序通过递归检查不同大小的子数组,最终找到正确的排序顺序。如果无法通过归并排序得到正确结果,则用插入排序作为备用方案。
摘要由CSDN通过智能技术生成

这里的归并和通常写的不一样。通常写的归并是对半的,即像如下形式:

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值