【堆中的路径】and 【L2-012. 关于堆的判断】 数组模拟建二叉树

将一系列给定数字插入一个初始为空的小顶堆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

分析: 我们真的建树的话会很麻烦,和线段树一样,我们用一维数组来模拟二叉树的结构,(因为其父节点和孩子节点的标号 很有规律)。
这里写图片描述
看代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N  = 1000+11;
const int M  = 1e6+11;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const LL inff = 0x3f3f3f3f3f3f3f3f;

int H[N],sz;
void Creat(){
    sz=0;
    H[0]=-inf;
}
void Insert(int x){
    int i;
    for(i=++sz;H[i/2]>x;i/=2) //  如果比父节点的值小那么就要交换一下,不断交换,直到大于父节点
        H[i]=H[i/2];
    H[i]=x;
}
void Out(int id){
    printf("%d",H[id]);
    while(id>1){
        id/=2;
        printf(" %d",H[id]);
    }
    puts("");
}

int main(){
    int n,m; scanf("%d%d",&n,&m);
    Creat();
    for(int i =0;i<n;i++){
        int z;scanf("%d",&z);
        Insert(z);
    }
    while(m--){
        int z;scanf("%d",&z);
        Out(z);
    }
return 0;
}

L2-012. 关于堆的判断

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

“x is the root”:x是根结点;
“x and y are siblings”:x和y是兄弟结点;
“x is the parent of y”:x是y的父结点;
“x is a child of y”:x是y的一个子结点。
输入格式:

每组测试第1行包含2个正整数N(<= 1000)和M(<= 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出“T”,否则输出“F”。

输入样例:
5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10
输出样例:
F
T
F
T
分析: 如果可以将上一个 建立二叉堆的方法学会,这个题目应该很简单吧。就是模拟而已。
代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
 / / 数据应该是默认的 都是不一样的数字,不然同一个数字其位置不唯一,就不好玩了
const int N  = 2e5+11;
const int M  = 1e6+11;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const LL inff = 0x3f3f3f3f3f3f3f3f;

int H[N],sz;
void Creat(){
    H[0]=-inf;
    sz=0;
}
void Insert(int x){
    int i=++sz;
    for(i;H[i/2]>x;i/=2) H[i]=H[i/2];
    H[i]=x;
}
int Find(int x){ // 找到x在 一维数组中的位置pos,pos/2就是其父节点的标号
    for(int i=1;i<=sz;i++){
        if(H[i]==x) return i;
    }
}
int main(){
    Creat();
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int x;scanf("%d",&x);
        Insert(x);
    }

    while(m--){ //  我只能够说 其输入真恶心,我是一个字符串一个字符串判定分离的
        int flag;
        int a;scanf("%d",&a);
        string x;cin>>x;
        if(x=="and"){
            int b;scanf("%d",&b);
            string t;  cin>>t; cin>>t;
            a=Find(a); b=Find(b);
            if(a/2 == b/2) flag=1;
            else flag=0;
        }else {
            string y;cin>>y;
            if(y=="a") {
                string t;  cin>>t; cin>>t;
                int b;scanf("%d",&b);
                a=Find(a) ; b=Find(b);
                if(a/2 == b) flag=1;
                else flag=0;
            }else {
                string z;cin>>z;
                if(z=="root"){
                    if(H[1]==a) flag=1;
                    else flag=0;
                }else {
                    string z;cin>>z;
                    int b;scanf("%d",&b);
                    a=Find(a) ;b=Find(b);
                    if(a==b/2) flag=1;
                    else flag=0;
                }
            }
        }

        if(flag) puts("T");
        else puts("F");
    }

return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值