1098. Insertion or Heap Sort (25)

题目地址:http://www.patest.cn/contests/pat-a-practise/1098

对于堆排序中间序列:6 4 5 1 0 3 2 7 8 9

首先 6 与 2 交换 数据变成:2 4 5 1 0 3 6 7 8 9(6,7,8,9已经排好了,前面的数据需要进行调整成大根堆)

    2
   /  \   4    5
 / \   /
1   0  3
从n/2处即5 开始调整 接着 4 接着 1
5 不需要调整 4 也不需要 2 需要调整,一直调整到叶子节点

    5                5
   /  \             /  \ 
  4    2    -〉    4    3      
 / \   /          / \   /
1   0  3         1   0  2

所以下一步的堆排序序列为 : 5 4 3 1 0 2 6 7 8 9
后面的排序同理 , 每次都需要交换 和 调整大堆树
/* 1098. Insertion or Heap Sort (25) http://www.patest.cn/contests/pat-a-practise/1098 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

#define N 105
int n ;
int a[N]; // initial sequence
int b[N]; // target sequence
int c[N]; // target sequence

bool cmp(int x, int y)
{
    return x < y ;
}

bool isOk()
{
    int i ;
    for(i = 0 ; i<n;i++)
    {
        if(a[i] != c[i] )
            return false;
    }
    return true;
}   

bool Insertion_sort()
{
    int i;
    for(i = 2;i <= n ;i++)
    {
        sort(a,a+i,cmp);
        if(isOk())
        {
            if(i < n)
            {
                sort(a,a+i+1,cmp);
            }else{
                sort(a,a+n,cmp);
            }
            return true;
        }
    }
    return false;
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n) != EOF )
    {
        int i;
        for(i = 0 ; i < n ; i ++)
        {
            scanf("%d",&a[i]);
        }
        for(i = 0 ; i <n ;i++)
        {
            scanf("%d",&c[i]);
            b[i] = c[i];
        }
        if( Insertion_sort() )
        {
            printf("Insertion Sort\n");
            printf("%d",a[0]);
            for(i =1 ; i < n ; i ++ )
            {
                printf(" %d",a[i]);
            }
            printf("\n");
        }else{
            // heap sort
            printf("Heap Sort\n");
            int firstNum = b[0];
            int pos = n - 1;
            while(b[pos] > firstNum)
                pos -- ;
            // swap
            int tmp = b[pos] ;
            b[pos] = firstNum;
            b[0] = tmp ;

            // 从n/2开始调整到根节点
            for(i = pos / 2 ;i >= 0 ; i--)
            {
                // 对每一个位置 , 不断的调整直到叶子节点
                int tpos = i - 1;
                while(2 * tpos - 1 <= pos - 1 && tpos >= 0)
                {
                    int nowData = b[tpos];
                    int left = -1 ; // 这里left right 先设置为非常小的数,此题用-1即可
                    int right = -1 ;
                    if(2*(tpos+1) - 1 <= pos - 1) // 根据二叉树 i 2*i 2*i+1 的关系
                        left = b[2*(tpos+1) - 1];
                    if(2*(tpos+1) <= pos - 1)
                        right = b[2*(tpos+1)];
                    if(nowData < left || nowData < right)
                    {
                        // 选取较大的交换, 同时更新tpos,递归调整直到叶子节点
                        if(left > right)
                        {
                            b[tpos] = left;
                            b[2*(tpos+1) - 1] = nowData;
                            tpos = 2*(tpos+1) - 1; 
                        }else{
                            b[tpos] = right;
                            b[2*(tpos+1)] = nowData;
                            tpos = 2*(tpos+1);
                        }
                    }else{
                        break;
                    }
                }
            } // for

            printf("%d",b[0]);
            for(i =1 ; i < n ; i ++ )
            {
                printf(" %d",b[i]);
            }
            printf("\n");

        } // else

    } // while
    return 0;
}

你可能感兴趣的:(1098. Insertion or Heap Sort (25))