C/C++数据结构——堆中的路径(插入小顶堆)

活动地址:CSDN21天学习挑战赛

题目描述

将一系列给定数字依次插入一个初始为空的小顶堆H[]。随后对任意给定的下标i,打印从H[i]到根结点的路径。

输入格式:

每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数、以及需要打印的路径条数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。最后一行给出M个下标。

输出格式:

对输入中给出的每个下标i,在一行中输出从H[i]到根结点的路径上的数据。数字间以1个空格分隔,行末不得有多余空格。

输入样例:

5 3
46 23 26 24 10
5 4 3

输出样例:

24 23 10
46 23 10
26 10

代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB

解题代码

#include<stdio.h>
void headAdjust(int *num,int len){
//调整堆,每次插入一个值都对堆自下向上进行一个调整。
    int k=len;
    num[0]=num[k];
    for(int i=len/2;num[i]>num[0];i/=2){
        num[k]=num[i];
        k=i;
    }
    num[k]=num[0];
}
int main()
{
    int num[1005];
    int len=0,n,m,inNum;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++){
            scanf("%d",&inNum);
            num[++len]=inNum;
            headAdjust(num,len);
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&inNum);
            while(inNum>=1){
                if(inNum==1)
                    printf("%d",num[inNum]);
                else
                    printf("%d ",num[inNum]);
                inNum/=2;
            }
            if(i!=m)//输出注意格式
            printf("\n");
        } 
    }
}

解题思路

就是一个简单的插入小顶堆,每次插入一个值的时候都与其上面的结点进行比较交换,小的放上面,大的放下面,然后一直交换到根节点就行。
输出的时候一直除2就行,就是要注意输出格式,这是PTA的题目,对格式的要求还是比较强的。
小顶堆就是将一个一个数组看作是一颗完全二叉树,即编号为i的结点左右子树分别是结点编号2i和2i+1。然后每个结点的需要满足结点i的值<=结点2i的值&&结点i的值<结点2i+1的值,满足上述条件才能成为小顶堆,结点值大于左右结点的为大顶堆。
用例解析
初始数组num,样例为46 23 26 24 10

下标123456789

当我们输入第一个值46时,数组内没数据,直接存放

下标123456789
46

​当我们输入值23时,先将其存放在下标为2的位置

下标123456789
4623

按照顶堆的规则,i的左右子树分别为2i和2i+1,也就是如下图所示

在这里插入图片描述

但是此时不符合小顶堆的规则,小顶堆应当符合num[i]<=num[2*i]&&num[i]<=num[2*i+1],即结点的值要小于左右结点值(大顶堆结点值要大于左右结点值),所以要进行交换。因为我们是从数组末尾插入结点,我们的插入结点要自下往上和他的根节点进行比较,如果根节点比他大则进行交换。得到如下结果。

下标123456789
2346

其他结点 也同样,插入之后自下向上比较替换即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祖安大龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值