zoukankan      html  css  js  c++  java
  • 【数组模拟-小顶堆的插入构造/遍历】PAT-L2-012.-关于堆的判断--数组模拟

    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的一个子结点。
    • (仔细观察,发现只有第二句第二个单词是“and”,除了第二个之外的句子全是第四个单词一定可以区分出来!!此中必有隐情吧,说不好出题人就是这么造数据的!!)

    输入格式:

    每组测试第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


    AC题解:(开数组模拟小顶堆即可)

    提醒:判断x和y是兄弟节点时,要注意y和x可能也是的;
      注意越界,枚举父节点时,跑n/2即可(具体原因参考二叉树的性质)!
      我写的debug()函数,输出堆的时候就是按照小顶堆的层序遍历来的!
      其实用链表写着更省内存!开数组需要多开一些(一倍吧,具体自己证明多少合适!)不然会发生段错误的当数据量取上限的时候,N=1000是不够的(我试了试--段错误),见构造函数的第20行代码:“if(heap[i<<1]==-1)return ;”
      因为每次访问到根节点,我用的判断方法是判断其是否还有左孩子节点!!所以————
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<vector>
    #include<string>
    #include<map>
    #define maxn 400000
    #define  inf 0x3f3f3f3f  //L2-012. 关于堆的判断
    using namespace std;
    #define N 2008
    int heap[N];
    int flag;
    int n;
    void min_heap_adjust(int i){//原则:把小的元素调整上去
        if(heap[i]==-1)return ;
        if(heap[i<<1]==-1)return ;
        int l=i<<1,r=i<<1|1;
        if(heap[r]==-1){
            if(heap[i]>heap[l]){
                swap(heap[i],heap[l]);
            }
        }else{
            int minn=heap[i],j=0;
            if(heap[l]<minn){
                j=l;minn=heap[l];
            }
            if(heap[r]<minn){
                j=r;
            }
            if(j!=0){
                swap(heap[j],heap[i]);
                min_heap_adjust(j);
            }
        }
    }
    int find_siblings(int i,int x,int y){//判断x和y是否是兄弟节点
        if(flag)return 1;
        if(i>n/2)return 0;
        int l=i<<1,r=i<<1|1;
        if(heap[l]==-1||heap[r]==-1)
            return 0;
        if((heap[l]==x&&heap[r]==y)  || (heap[r]==x&&heap[l]==y))
            return flag=1;
        find_siblings(i<<1,x,y);
        find_siblings(i<<1|1,x,y);
        return 0;
    }
    int find_parent(int i,int x,int y){//判断x是y的父亲
        if(flag)return 1;
        if(i>n/2)return 0;
        int l=i<<1,r=i<<1|1;
        if(heap[i]==x){
            if(heap[l]!=-1){
                if(heap[l]==y)return flag=1;
            }
            if(heap[r]!=-1){
                if(heap[r]==y)return flag=1;
            }
        }
        find_parent(i<<1,x,y);
        find_parent(i<<1|1,x,y);
        return 0;
    }
    
    void solve(int n){
        int x,y;
        flag=0;//初始化一次标志数
        scanf("%d",&x);
        char s[10];
        scanf("%s",s);
        if(s[0]=='a'){
            scanf("%d%*s%*s",&y);//求x和y是否兄弟节点
            find_siblings(1,x,y);
        }else{
            scanf("%*s%s",s);
            if(s[0]=='r'){
                if(heap[1]==x)flag=1;
            }
            else if(s[0]=='p'){//判断x是y的父亲
                scanf("%*s%d",&y);
                find_parent(1,x,y);
            }
            else{
                scanf("%*s%d",&y);
                find_parent(1,y,x);
            }
        }
        if(flag==1)printf("T
    ");
        else printf("F
    ");
    
        return ;
    }
    void debug(){
        for(int i=1;i<=n;i++)
            printf("%d ",heap[i]);
        cout<<endl;
    }
    int main(){
        int m;
        int num;
        while(scanf("%d%d",&n,&m)!=EOF){
            memset(heap,-1,sizeof(heap));
            for(int i=1;i<=n;i++){
                scanf("%d",&num);
                heap[i]=num;
                for(int j=i/2;j>=1;j--){
                    min_heap_adjust(j);
                }
            }
    
           // debug();
            for(int i=1;i<=m;i++)
                solve(n);
        }
    
        return 0;
    }
    View Code


  • 相关阅读:
    使用VB获得系统目录路径
    自动点击页面中的JavaScript链接
    vb 随机数
    进程监控程序 监视进程的创建
    UTF8 Encoding rules
    How to create and apply patch by GIT
    Java Access Bridge Why IsJavaWindow always returns false?
    TomatoUSB 挂载了/jffs/opt之后登录出现$提示符以及VI内存耗尽等各种异常
    MMU解释 MMU启用后,CPU的内存访问请求会被MMU截获
    如何调整Linux内核启动中的驱动初始化顺序
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/8567446.html
Copyright © 2011-2022 走看看