• PAT甲级【2019年3月考题】——A1159 Structure_of_a_BinaryTree【30】


    Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, a binary tree can be uniquely determined.

    Now given a sequence of statements about the structure of the resulting tree, you are supposed to tell if they are correct or not. A statment is one of the following:

    A is the root
    A and B are siblings
    A is the parent of B
    A is the left child of B
    A is the right child of B
    A and B are on the same level
    It is a full tree
    Note:
    Two nodes are on the same level, means that they have the same depth.
    A full binary tree is a tree in which every node other than the leaves has two children.
    Input Specification:
    Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are no more than 103 10^310
    3
    and are separated by a space.

    Then another positive integer M (≤30) is given, followed by M lines of statements. It is guaranteed that both A and B in the statements are in the tree.

    Output Specification:
    For each statement, print in a line Yes if it is correct, or No if not.

    Sample Input:
    9
    16 7 11 32 28 2 23 8 15
    16 23 7 32 11 2 28 15 8
    7
    15 is the root
    8 and 2 are siblings
    32 is the parent of 11
    23 is the left child of 16
    28 is the right child of 2
    7 and 11 are on the same level
    It is a full tree
    Sample Output:
    Yes
    No
    Yes
    No
    Yes
    Yes
    Yes

    【声明】

      由于此题还未上PAT官网题库,故没有测试集,仅仅是通过了样例,若发现错误,感谢留言指正。

    Solution:

      这道题不难,先通过后序和中序重构整颗二叉树,在重构时,使用hash表来存储每个节点值对应的节点,这样就可以解决后面询问是不是父节点和左右子节点的问题。

      然后使用DFS来遍历整棵树,得到每个节点的深度值,其中记得记录每个节点的姐妹节点是谁,并进行判断是不是完整二叉树。

      到此,对于题目中的7个问题都有相应的记录进行解决

      唯一麻烦的是,对于问题的处理,题目是输入一整句话,那么判断属于哪个问题和将其中的关键数字取出来就比较麻烦,我是使用string中的find来判断属于哪个问题,并使用循环来获取数字,当然你也可以使用istringstream函数进行切割获取数据。

      1 #include <iostream>
      2 #include <queue>
      3 #include <vector>
      4 #include <string>
      5 #include <unordered_map>
      6 using namespace std;
      7 struct Node
      8 {
      9     int val;
     10     Node *l, *r;
     11     Node(int a = 0) :val(a), l(nullptr), r(nullptr) {}
     12 };
     13 int n, m;
     14 bool isfullTree = true;
     15 vector<int>post, in, siblings(1010, -1), level(1010, -1);
     16 unordered_map<int, Node*>map;
     17 Node* creatTree(int inL, int inR, int postL, int postR)//重建二叉树
     18 {
     19     if (inL > inR)
     20         return nullptr;
     21     Node *root = new Node(post[postR]);
     22     map[root->val] = root;//记录节点对应的key值
     23     int k = inL;
     24     while (k <= inR && in[k] != post[postR])++k;
     25     int nums = k - inL;
     26     root->l = creatTree(inL, k - 1, postL, postL + nums - 1);
     27     root->r = creatTree(k + 1, inR, postL + nums, postR - 1);
     28     return root;
     29 }
     30 void DFS(Node *root, int L)
     31 {
     32     if (root == nullptr)
     33         return;
     34     if ((root->l == nullptr && root->r) || (root->r == nullptr && root->l))
     35         isfullTree = true;//不是完全二叉树
     36     level[root->val] = L;//记录层数
     37     if (root->l&& root->r)//记录姐妹节点
     38     {
     39         siblings[root->l->val] = root->r->val;
     40         siblings[root->r->val] = root->l->val;
     41     }
     42     DFS(root->l, L + 1);
     43     DFS(root->r, L + 1);
     44 }
     45 vector<int> getNumber(const string &str, bool isOneNumber)//获取数据
     46 {
     47     vector<int>res;
     48     int a = 0;
     49     for (int i = 0; i < str.length(); ++i)
     50     {
     51         if (isdigit(str[i]))
     52             a = a * 10 + str[i] - '0';
     53         else if (a > 0)
     54         {
     55             res.push_back(a);
     56             a = 0;
     57             if (isOneNumber || res.size() == 2)//就输出一个字符就行
     58                 break;
     59         }
     60     }
     61     if (!isOneNumber && res.size() < 2)//获取处于最后的数字
     62         res.push_back(a);
     63     return res;
     64 }
     65 int main()
     66 {
     67     cin >> n;
     68     post.resize(n);
     69     in.resize(n);
     70     for (int i = 0; i < n; ++i)
     71         cin >> post[i];
     72     for (int i = 0; i < n; ++i)
     73         cin >> in[i];
     74     Node *root = creatTree(0, n - 1, 0, n - 1);
     75     DFS(root, 1);//获取层数
     76     cin >> m;
     77     getchar();
     78     while (m--)
     79     {
     80         string str;
     81         getline(cin, str);
     82         if (str.find("root", 0) != -1)//查询根节点
     83         {
     84             vector<int>res = getNumber(str, true);
     85             if (root->val == res[0])
     86                 printf("Yes
    ");
     87             else
     88                 printf("No
    ");
     89         }
     90         else if (str.find("siblings", 0) != -1)//查询姐妹节点
     91         {
     92             vector<int>res = getNumber(str, false);            
     93             if (siblings[res[0]] == res[1])
     94                 printf("Yes
    ");
     95             else
     96                 printf("No
    ");
     97         }
     98         else if (str.find("parent", 0) != -1)//查询父节点
     99         {
    100             vector<int>res = getNumber(str, false);
    101             if ((map[res[0]]->l && map[res[0]]->l->val == res[1]) ||
    102                 (map[res[0]]->r && map[res[0]]->r->val == res[1]))
    103                 printf("Yes
    ");
    104             else
    105                 printf("No
    ");
    106         }
    107         else if (str.find("left", 0) != -1)//左节点
    108         {
    109             vector<int>res = getNumber(str, false);
    110             if (map[res[1]]->l && map[res[1]]->l->val == res[0])
    111                 printf("Yes
    ");
    112             else
    113                 printf("No
    ");
    114         }
    115         else if (str.find("right", 0) != -1)//右节点
    116         {
    117             vector<int>res = getNumber(str, false);
    118             if (map[res[1]]->r && map[res[1]]->r->val == res[0])
    119                 printf("Yes
    ");
    120             else
    121                 printf("No
    ");
    122         }
    123         else if (str.find("level", 0) != -1)//同样的深度
    124         {
    125             vector<int>res = getNumber(str, false);
    126             if (level[res[0]]==level[res[1]])
    127                 printf("Yes
    ");
    128             else
    129                 printf("No
    ");
    130         }
    131         else if (str.find("full", 0) != -1)//是不是完整二叉树
    132         {
    133             if (isfullTree)
    134                 printf("Yes
    ");
    135             else
    136                 printf("No
    ");
    137         }
    138     }
    139     return 0;
    140 }

    我的代码有点繁琐,后然我逛博客发现了一个更简便的字符处理函数sscanf,还有就是由于重构二叉树的同时就是一个DFS的过程,这样我们就可以将其深度值得到。当然,我感觉我的代码还是有点优点的,不是么 ^_^.

    附带博主代码:

     1 #include<iostream>
     2 #include<vector>
     3 #include<queue>
     4 #include<algorithm>
     5 #include<string>
     6 #include<cstring>
     7 #include<unordered_map>
     8 #include<unordered_set>
     9 using namespace std;
    10 const int maxn=1005;
    11 const int INF=0x3f3f3f3f;
    12 unordered_map<int,int> level,parents;
    13 struct node {
    14     int data;
    15     int layer;
    16     node *lchild,*rchild;
    17 };
    18 vector<int> post,in;
    19 node* newNode(int data,int layer) {
    20     node* root=new node;
    21     root->data=data;
    22     root->layer=layer;
    23     level[data]=layer;
    24     root->lchild=root->rchild=NULL;
    25     return root;
    26 }
    27 bool flag=true;
    28 node* create(int parent,int postLeft,int postRight,int inLeft,int inRight,int layer) {
    29     if(postLeft>postRight) return NULL;
    30     node* root=newNode(post[postRight],layer);
    31     parents[root->data]=parent;
    32     int index=inLeft;
    33     while(in[index]!=root->data) index++;
    34     int numLeft=index-inLeft;
    35     root->lchild=create(root->data,postLeft,postLeft+numLeft-1,inLeft,index-1,layer+1);
    36     root->rchild=create(root->data,postLeft+numLeft,postRight-1,index+1,inRight,layer+1);
    37     //如果有叶子,就必须有两片叶子
    38     if((root->lchild || root->rchild ) && (!root->lchild || !root->rchild)) flag=false;
    39     return root;
    40 }
    41 int main() {
    42     int n,m;
    43     unordered_map<int,int> ppos,ipos;
    44     scanf("%d",&n);
    45     post.resize(n);
    46     in.resize(n);
    47     for(int i=0; i<n; i++) {
    48         scanf("%d",&post[i]);
    49         ppos[post[i]]=i;
    50     }
    51     for(int i=0; i<n; i++) {
    52         scanf("%d",&in[i]);
    53         ipos[in[i]]=i;
    54     }
    55     node* root = create(n-1,0,n-1,0,n-1,0);
    56     scanf("%d
    ",&m);
    57     string ask;
    58     for(int i=0; i<m; i++) {
    59         getline(cin,ask);
    60         int num1=0,num2=0;
    61         if(ask.find("root")!=string::npos) {
    62             sscanf(ask.c_str(),"%d is the root",&num1);
    63             if(ppos[num1]==n-1) puts("Yes");
    64             else puts("No");
    65         } else if(ask.find("siblings")!=string::npos) {
    66             sscanf(ask.c_str(),"%d and %d are siblings",&num1,&num2);
    67             if(level[num1]==level[num2] && parents[num1]==parents[num2]) puts("Yes");
    68             else puts("No");
    69         } else if(ask.find("parent")!=string::npos) {
    70             sscanf(ask.c_str(),"%d is the parent of %d",&num1,&num2);
    71             if(parents[num2]==num1) puts("Yes");
    72             else puts("No");
    73         } else if(ask.find("left")!=string::npos) {
    74             sscanf(ask.c_str(),"%d is the left child of %d",&num1,&num2);
    75             if(parents[num1]==num2 && ipos[num1]<ipos[num2]) puts("Yes");
    76             else puts("No");
    77         } else if(ask.find("right")!=string::npos) {
    78             sscanf(ask.c_str(),"%d is the right child of %d",&num1,&num2);
    79             if(parents[num1]==num2 && ipos[num1]>ipos[num2]) puts("Yes");
    80             else puts("No");
    81         } else if(ask.find("same")!=string::npos) {
    82             sscanf(ask.c_str(),"%d and %d are on the same level",&num1,&num2);
    83             if(level[num1]==level[num2]) puts("Yes");
    84             else puts("No");
    85         } else if(ask.find("full")!=string::npos) {
    86             if(flag) puts("Yes");
    87             else puts("No");
    88         }
    89     }
    90     return 0;
    91 }

      

  • 相关阅读:
    如何快速生成API并进行测试
    如何开始使用接口自动化测试脚本
    一些网上密码学资源(转载)
    手把手硬件电路详细设计过程(转载)
    触发器(trigger)的作用???
    去面试字节跳动啦!
    2020年白领年终奖报告来了,平均值为7826元
    12 个顶级 Bug 跟踪工具
    接口的幂等性怎么设计?
    魔改一波合成大西瓜!代码已开源~
  • 原文地址:https://www.cnblogs.com/zzw1024/p/11954451.html
Copyright © 2020-2023  润新知