zoukankan      html  css  js  c++  java
  • PAT A1098 Insertion or Heap Sort (25分)(初始序列不参与是否与目标序列相同&&堆排序)


    题目大意:给出n和n个数的序列a和b,a为原始序列,b为排序其中的一个步骤,问b是a经过了堆排序还是插入排序的,并且输出它的下一步~

    分析:插入排序的特点是:b数组前面的顺序是从小到大的,后面的顺序不一定,但是一定和原序列的后面的顺序相同~所以只要遍历一下前面几位,遇到不是从小到大的时候,开始看b和a是不是对应位置的值相等,相等就说明是插入排序,否则就是堆排序啦~

    插入排序的下一步就是把第一个不符合从小到大的顺序的那个元素插入到前面已排序的里面的合适的位置,那么只要对前几个已排序的+后面一位这个序列sort排序即可~while(p <= n && b[p - 1] <= b[p]) p++;int index = p;找到第一个不满足条件的下标p并且赋值给index,b数组下标从1开始,所以插入排序的下一步就是sort(b.begin() + 1, b.begin() + index + 1)后的b数组~

    堆排序的特点是后面是从小到大的,前面的顺序不一定,又因为是从小到大排列,堆排序之前堆为大顶堆,前面未排序的序列的最大值为b[1],那么就可以从n开始往前找,找第一个小于等于b[1]的数字b[p](while(p > 2 && b[p] >= b[1]) p--;),把它和第一个数字交换(swap(b[1], b[p]);),然后把数组b在1~p-1区间进行一次向下调整(downAdjust(b, 1, p - 1);)~向下调整,low和high是需要调整的区间,因为是大顶堆,就是不断比较当前结点和自己的孩子结点哪个大,如果孩子大就把孩子结点和自己交换,然后再不断调整直到到达区间的最大值不能再继续了为止~

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N = 110;
    vector<int> list,target,temp;
    int n;
    
    bool insertsort(){
        temp = list;
        for(int i = 1;i<n;i++){
            sort(temp.begin(),temp.begin()+i);
            if(i!=1&&temp==target){
                sort(temp.begin(),temp.begin()+i+1);
                return true;
            }
        }
        return false;
        
    }
    void downadjust(int low,int high){
        int i  = low,j = 2*i+1;
        while(j<=high){
            if(j+1<=high&&temp[j+1]>temp[j]){
                j = j+1;
            }
            if(temp[j]>temp[i]){
                swap(temp[j],temp[i]);
                i = j;
                j = 2*i+1;
            }else{
                break;
            }
        }
        
    }
    
    bool heapsort(){
        temp = list;
        for(int i = n/2;i>=0;i--){
            downadjust(i,n-1);
        }
        for(int i  = n-1;i>0;i--){
            if(i!=n-1&&temp==target){
               swap(temp[i],temp[0]);
                downadjust(0,i-1);
                return true;
            }
            swap(temp[i],temp[0]);
            downadjust(0,i-1);
        }
        return false;
    }
    int main(){
        scanf("%d",&n);
        for(int i = 0;i<n;i++){
            int num;
            scanf("%d",&num);
            list.push_back(num);
        }
        for(int i = 0;i<n;i++){
            int num;
            scanf("%d",&num);
            target.push_back(num);
        }    
        //insertsort
        if(insertsort()==true){
            printf("Insertion Sort
    ");
            for(int i = 0;i<n;i++){
                printf("%d",temp[i]);
                if(i!=n-1) printf(" ");
            }
        }else if(heapsort()==true){
            printf("Heap Sort
    ");
            for(int i = 0;i<n;i++){
                printf("%d",temp[i]);
                if(i!=n-1) printf(" ");
            }        
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)
    Java线程面试题 Top 50 (个人总结)(转)
    rabbitMQ windows 安装 入门(转)
    Java并发编程:volatile关键字解析(学习总结-海子)
    关于Sychronized和volatile自己总结的一点点理解(草稿)
    FWORK-数据存储篇 -- 范式与反模式 (学习和理解)
    Synchronized的原理及自旋锁,偏向锁,轻量级锁,重量级锁的区别(摘抄和理解)
    vcfc之zk+postsql+keystore(cassandra)框架分析
    CAP理论-解析
    java多线程通信 例子
  • 原文地址:https://www.cnblogs.com/shuibeng/p/13657521.html
Copyright © 2011-2022 走看看