【PAT A1098】Insertion or Heap Sort

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 110;

int origin[N], tempori[N], changed[N]; //原始数组、临时数组(原始数组备份)及目标数组
int n; //元素个数

bool isSame(int A[], int B[]) //判断数组A和数组B是否相同
{
    for(int i = 1; i <= n; i++) //循环遍历
    {
        if(A[i] != B[i]) //如果有一个不相同,直接返回false
            return false;
    }
    return true; //到这一步说明每个元素都相同,返回true
}

void showArray(int A[]) //输出数组
{
    for(int i = 1; i <= n; i++)
    {
        printf("%d", A[i]);
        if(i < n)
            printf(" ");
    }
    printf("\n");
}

bool insertSort() //插入排序
{
    bool flag = false; //记录是否存在数组tempori[]中间步骤与changed[]数组相同
    for(int i = 2; i <= n; i++) //总共可能进行n - 1趟,实际不一定有
    {
        if(i != 2 && isSame(tempori, changed)) //中间临时数组与目标数组相同
            flag = true;                       //并且不是初始序列
        
        sort(tempori, tempori + i + 1); //插入部分直接用sort()函数代替
        if(flag == true) //如果flag为true,则说明有中间数组匹配上目标数组,返回true
            return true;
    }
    return false; //无法匹配上目标数组,返回false
}

void downAdjust(int low, int high) //对heap数组在[low, high]范围内进行调整
{ //其中low为 欲调整结点的 数组下标,high一般为 堆的 最后一个元素的 数组下标
    int i = low, j= i * 2;  //i为欲调整结点,j为其左孩子结点
    while(j <= high) //存在孩子结点
    {   //如果右孩子结点存在,且右孩子结点值大于左孩子结点值
        if(j + 1 <= high && tempori[j + 1] > tempori[j])
        {
            j = j + 1; //让j存储右孩子结点下标
        }
        if(tempori[j] > tempori[i]) //如果孩子结点中最大的权值比父亲结点大
        {
            swap(tempori[j], tempori[i]); //交换最大权值的孩子结点与父亲结点
            i = j; //令i为j
            j = i * 2; //令j为i的左孩子结点,进入下一层
        }
        else{
            break; //孩子结点的权值均比父亲结点的小,调整结束
        }
    }
}

void heapSort() //堆排序
{
    bool flag = false;
    for(int i = n / 2; i >= 1; i--)
    {
        downAdjust(i, n); //建堆,此时是从大到小的顺序
    }
    
    for(int i = n; i > 1; i--)
    {
        if( i != n && isSame(tempori, changed)) //中间临时数组序列与目标序列相同
            flag = true;                         //并且不是初始序列
        swap(tempori[i], tempori[1]); //交换heap[i]与堆顶
        downAdjust(1, i - 1); ///调整堆顶
        if(flag == true) //如果临时数组匹配上目标数组
        {
            showArray(tempori); //输出数组
            return;
        }
    }
}


int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &origin[i]); //输入起始数组
        tempori[i] = origin[i]; //tempori数组为备份,排序在tempori上进行
    }
    
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &changed[i]); //输入目标数组
    }
    
    if(insertSort()) //如果插入排序中找到目标数组
    {
        printf("Insertion Sort\n");
        showArray(tempori);
    }
    else{ //到达此处时一定是堆排序
        printf("Heap Sort\n");
        for(int i = 1; i <= n; i++)
        {
            tempori[i] = origin[i]; //还原tempori数组
        }
        heapSort(); //堆排序
    }
    
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值