PAT 1098. Insertion or Heap Sort (25)

来源:互联网 发布:网络的消极作用 编辑:程序博客网 时间:2024/06/05 05:12

According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Heap sort divides its input into a sorted and an unsorted region, and it iteratively shrinks the unsorted region by extracting the largest element and moving that to the sorted region. it involves the use of a heap data structure rather than a linear-time search to find the maximum.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (<=100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in the first line either "Insertion Sort" or "Heap Sort" to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resuling sequence. It is guaranteed that the answer is unique for each test case. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

Sample Input 1:
103 1 2 8 7 5 9 4 6 01 2 3 7 8 5 9 4 6 0
Sample Output 1:
Insertion Sort1 2 3 5 7 8 9 4 6 0
Sample Input 2:
103 1 2 8 7 5 9 4 6 06 4 5 1 0 3 2 7 8 9
Sample Output 2:
Heap Sort5 4 3 1 0 2 6 7 8 9


题目大意

本题考查插入排序和堆排的具体过程。两个有n个不同数的数组a[]、b[],a[]是原始序列,b[]是插排或堆排进行几次操作后的序列。

首先判断是插排还是堆排,分别输出(Insertion Sort、Heap Sort)。

接着输出该排序下一步完成后的序列。

题目解析

首先判断属于哪个排序:利用插排的特点,b[]数组前面是递增的,后面是跟a[]后面对应相等。否则就是堆排。

无论是插排还是堆排,都需要先判断一个需要排序的分割点。

对于插排分割点就是:第一个当前数字大于后一个数字的位置。

对于堆排分割点就是:递增序列中与b[]从后遍历相比较,第一个不同的数就是分割点。

样例:

第一个样例:

1 2 3 7 8 5 9 4 6 0
红5的位置是小于前面一个8的,一次下一个要排的位置就是红5

第二个样例:

样例中的排序:6 4 5 1 0 3 2 7 8 9
整个数组排序完:0 1 2 3 4 5 6 7 8 9

两个数组从后往前比第一个不相等的数就是要排序位置的分割点。

最后堆排的过程,维护一个大顶堆即可。

#include <cstdio>#include <cmath>#include <vector>#include <map>#include <set>#include <queue>#include <stack>#include <cstdlib>#include <climits>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define ll long longconst int MAXN = 100 + 5;const int MAXM = 100000 + 5;const int INF = 0x7f7f7f7f;const int dir[][2] = {0,1,1,0,0,-1,-1,0};template <class XSD> inline XSD f_min(XSD a, XSD b) { if (a > b) a = b; return a; }template <class XSD> inline XSD f_max(XSD a, XSD b) { if (a < b) a = b; return a; }int n;int a[MAXN], b[MAXN];int c[MAXN], tree[1005];int Is_insertion(){///判断是否是插入排序    int di;    for(int i=n; i>=1; i--) if(b[i]!=a[i]) {di=i;break;}    sort(c+1, c+di+1);    for(int i=1; i<=di; i++) if(c[i]!=b[i]) return 0;    for(int i=1; i<=n; i++) if(b[i]>b[i+1]) return i;///插入排序的第一个“前一个大于后一个的”,要排的就是下一个}void Getdata(){    for(int i=1; i<=n; i++) scanf("%d", &a[i]), c[i]=a[i];    for(int i=1; i<=n; i++) scanf("%d", &b[i]);}void Dfs(int root){    int l=root<<1, r=l+1, t;    if(tree[r]!=-1){///左右子树都存在,选择较大的一个和根比较        if(tree[l]>tree[r] && tree[root]<tree[l]){            t=tree[root], tree[root]=tree[l], tree[l]=t;            Dfs(l);        }        else if(tree[l]<tree[r] && tree[root]<tree[r]){            t=tree[root], tree[root]=tree[r], tree[r]=t;            Dfs(r);        }    }    else if(tree[l]==-1 && tree[r]==-1) return;///左右子树均不存在    else if(tree[l]!=-1 && tree[r]==-1){///只存在左子树        if(tree[root]<tree[l]) t=tree[root], tree[root]=tree[l], tree[l]=t;    }}void Solve(){    int x=Is_insertion();    if(x){///插入排序操作        printf("Insertion Sort\n");        int pos, num=b[x+1];        for(int i=1; i<=x; i++) if(b[x+1]<b[i]){pos=i;break;}        for(int i=x+1; i>pos; i--) b[i]=b[i-1];        b[pos]=num;    }    else{///堆排操作        printf("Heap Sort\n");        memset(tree, -1, sizeof tree);        int pos=0, max_=0, tpos=0, t;        sort(a+1, a+n+1);        for(int i=n; i>=1; i--) if(a[i]!=b[i]) {pos=i;break;}        for(int i=1; i<=pos; i++){///选取前面乱序的最大的            if(i!=pos) tree[i]=b[i];            if(max_<b[i]) tpos=i, max_=b[i];        }        tree[tpos]=b[pos], b[pos]=b[tpos];///tree是前面乱序的数        Dfs(1);        for(int i=1; i<=pos-1; i++) b[i]=tree[i];    }    ///输出    for(int i=1; i<=n; i++) printf("%d%c", b[i], i==n?'\n':' ');}int main(){    while(~scanf("%d", &n)){        Getdata();        Solve();    }    return 0;}


0 0
原创粉丝点击