1035. 插入与归并(25)

1035. 插入与归并(25)

时间限制 200 ms
内存限制 65536 kB
代码长度限制 8000 B
判题程序 Standard
作者 CHEN, Yue

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成N个只包含1个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下1个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数N (<=100);随后一行给出原始序列的N个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行末不得有多余空格。
输入样例1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出样例1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
输入样例2:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
输出样例2:
Merge Sort
1 2 3 8 4 5 7 9 0 6

原题地址: https://www.patest.cn/contests/pat-b-practise/1035


思路:判断是那种排序,可以对原数组进行排序,每排完一趟都和中间数组进行比较一下就可以了
这道题考的是深入理解插入排序和归并排序,也让我学了一下归并排序(递归算法和非递归算法, 这道题只能用非递归了),也更加熟悉了插入排序。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;

int N;
int A[100], T[100];

//判断B数组是否等于T数组 
bool IsEqual(int B[])
{
    for(int i = 0; i < N; i ++){
        if(B[i] != T[i])
            return false;
    }
    return true;
}

void Print(int B[])
{
    for(int i = 0; i < N; i ++){
        cout << B[i];
        if(i + 1 < N)
            cout << " "; 
    }
}

//将a的[low, mid), [mid, high) 两部分归并 
void Merge(int a[], int low, int mid, int high)
{
    int t[high - low];
    int i = low, j = mid, k = 0;

    while(i < mid && j < high){
        if(a[i] <= a[j])
            t[k ++] = a[i ++];
        else
            t[k ++] = a[j ++];
    }

    while(i < mid)
        t[k ++] = a[i ++];
    while(j < high)
        t[k ++] = a[j ++];

    for(i = low, k = 0; i < high; i ++){
        a[i] = t[k ++];
    }
}


void solve()
{
    int B[100];
    for(int i = 0; i < N; i ++){
        B[i] = A[i];
    }

    //归并排序检测 
    bool isMerge = false;
    for(int k = 1; k < N; k *= 2){
        for(int i = 0; i < N; i += k*2){
            if(i + k*2 <= N)
                Merge(B, i, i + k, i + 2*k);
            else if(i + k <= N)
                Merge(B, i, i + k, N);
        }

        if(isMerge){
            cout << "Merge Sort" << endl;
            Print(B);
            return;
        }
        else if(IsEqual(B)){
            isMerge = true;
        }

    }

    for(int i = 0; i < N; i ++){
        B[i] = A[i];
    }

    //插入排序检测 
    bool isInsert = false;
    for(int i = 1; i < N; i ++){
        int j, key = B[i];
        for(j = i - 1; B[j] > key && j >= 0; j --){
            B[j + 1] = B[j];
        }
        B[j + 1] = key;

        if(isInsert){
            cout << "Insertion Sort" << endl;
            Print(B);
            return;
        }
        else if(IsEqual(B)){
            isInsert = true;
        }

    }
}

int main()
{
    cin >> N;
    for(int i = 0; i < N; i ++){
        cin >> A[i];
    }
    for(int i = 0; i < N; i ++){
        cin >> T[i];
    }
    solve();
    return 0;
}

归并排序介绍:百度百科

这里也贴上我写的归并算法:

#include <iostream>
using namespace std;

// 对a的[low, mid), [mid, high)两部分归并
void Merge(int a[], int low, int mid, int high)
{
    int t[high - low];  // 中间数组
    int i = low, j = mid, k = 0;

    while (i < mid && j < high)
    {
        if (a[i] <= a[j])
            t[k++] = a[i++];
        else
            t[k++] = a[j++];
    }

    while (i < mid)
        t[k++] = a[i++];
    while (j < high)
        t[k++] = a[j++];

    for (i = low, k = 0; i < high; i++)
    {
        a[i] = t[k++];
    }
}

// 对a的[low, high)部分归并排序(递归)
void MergeSort(int a[], int n)
{
    if (n > 1)
    {
        // 将两部分分别进行归并排序
        MergeSort(a, n/2);
        MergeSort(a + n/2, n - n/2);

        // 将两部分归并
        Merge(a, 0, n/2, n);
    }
}

// 对a的[low, high)部分归并排序(非递归) 
void MergeSort2(int a[], int n)
{
    for (int k = 1; k < n; k *= 2)
    {
        for (int i = 0; i < n; i += k * 2)
        {
            if (i + 2 * k <= n)
                Merge(a, i, i + k, i + 2 * k);
            else if (i + 2 * k > n && i + k <= n)
                Merge(a, i, i + k, n);
        }
    }
}

void Print(int a[], int n)
{
    for(int i = 0; i < n; i ++){
        cout << a[i] << " "; 
    }
    cout << endl; 
}



int main()
{
    {
        int a[] = { 5, 3, 7, 9, 8, 4, 6, 1, 2, 10, 0, -1};
        MergeSort(a, 12);
        Print(a, 12);
    }

    {
        int a[] = { 5, 3, 7, 9, 8, 4, 6, 1, 2, 10, 0, -1};
        MergeSort2(a, 12);
        Print(a, 12);
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值