7-4 Structure of a Binary Tree (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.
  • 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 10​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

题目大意:给一个后序和中序序列构成一棵树,让你然后判断一些语句的对错。

语句类型:

  • A is the root
  • A and B are siblings (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

分析:

1)数据结构定义

静态链表和二叉链表都可以,这里采用二叉链表存储。便于判断父子关系和结点level,结构体这样定义;

struct node{
    int val,level;
    node* parent;
    node* l,*r;
};

2)建树

对往常后序和中序建树模板稍加改动即可:模板

在创建过程存储下当前val域与root指针的映射关系:nodes[root->val]=root(因为判断语句采用nodes【】判断),并将孩子结点的parent域(孩子结点非空)指向root即可 (emmm,突然发现个小bug,如果有root->val,那指针就覆盖了)

核心代码:

node *creat(int postl,int postr,int inl,int inr){
	if(postl>postr) return NULL;
	node *root=new node;
	root->val=post[postr];  
	nodes[root->val]=root; //存指针
	int k=inl;
	while(k<=inr && in[k]!=root->val) k++;
	int leftnum=k-inl;
	root->l =creat(postl,postl+leftnum-1,inl,k-1);
	root->r =creat(postl+leftnum,postr-1,k+1,inr);
	if (root->l) root->l->parent=root;
        if (root->r) root->r->parent=root;
	return root;
}

3)遍历树获取有效信息

前面两部已经获取到了父子关系啥的,现在只需要遍历过程得到高度和进行full tree判断,那么深搜一下即可。对于full tree判断这里采用反证法 (初始化is_full=true)

void dfs(node* root){ //获得高度和full树判断 
    if (!root) return;
    if (root->parent) root->level=root->parent->level+1; //根节点没有parent,得判断 
    if (root->l && !root->r) is_full=false;//只有左子树或者右子树则不是full tree 
    if (!root->l && root->r) is_full=false;
    dfs(root->l);
    dfs(root->r);
}

4)判断语句读取

如果常规cin>>str,那么肯定要写很多if else判断 ,容易搞混且代码不简洁,这里采用sscanf()大法:更多介绍

一点说明:sscanf() - 从一个字符串中读进与指定格式相符的数据.
函数原型:
  int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
  int scanf( const char *format [,argument]... );
说明:
  sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。

读入示例:

if (str.find("left child") != string::npos) {
            sscanf(str.c_str(), "%d is the left child of %d", &a, &b);

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=50;
struct node{
    int val,level;
    node* parent;
    node* l,*r;
};

bool is_full=true;
unordered_map<int, node*> nodes;
int post[maxn],in[maxn];

node *creat(int postl,int postr,int inl,int inr){
	if(postl>postr) return NULL;
	node *root=new node;
	root->val=post[postr];  
	nodes[root->val]=root; //存指针
	int k=inl;
	while(k<=inr && in[k]!=root->val) k++;
	int leftnum=k-inl;
	root->l =creat(postl,postl+leftnum-1,inl,k-1);
	root->r =creat(postl+leftnum,postr-1,k+1,inr);
	if (root->l) root->l->parent=root;
        if (root->r) root->r->parent=root;
	return root;
}

void dfs(node* root){ //获得高度和full树判断 
    if (!root) return;
    if (root->parent) root->level=root->parent->level+1;
    if (root->l && !root->r) is_full=false;
    if (!root->l && root->r) is_full=false;
    dfs(root->l);
    dfs(root->r);
}

int main(){
	int m,n;
	cin>>n;
    for(int i=0;i<n;i++) cin>>post[i];
    for(int i=0;i<n;i++) cin>>in[i];
    node* root=creat(0,n-1,0,n-1);
    root->level=1;
    dfs(root);
    cin>>m;
	getchar();
    while(m--){
        bool flag;
        int a,b;
        string str;
        getline(cin, str);
        if(str.find("root")!=string::npos){
            sscanf(str.c_str(),"%d is the root",&a);
            flag=(a==root->val)?1:0;
        }else if(str.find("siblings")!=string::npos){
            sscanf(str.c_str(), "%d and %d are siblings",&a,&b);
            flag=(nodes[a]->parent==nodes[b]->parent)?1:0;
        }else if(str.find("parent")!=string::npos){
            sscanf(str.c_str(),"%d is the parent of %d",&a,&b);
            flag=(nodes[b]->parent==nodes[a])? 1:0;
        }else if(str.find("left child")!=string::npos){
            sscanf(str.c_str(),"%d is the left child of %d",&a,&b);
            flag=(nodes[b]->l==nodes[a])? 1:0;
        }else if(str.find("right child")!=string::npos){
            sscanf(str.c_str(), "%d is the right child of %d",&a,&b);
            flag=(nodes[b]->r==nodes[a])? 1:0;
        }else if(str.find("same level")!=string::npos){
            sscanf(str.c_str(), "%d and %d are on the same level", &a, &b);
            flag=(nodes[a]->level==nodes[b]->level)? 1:0;
        }else{
            flag=is_full;
        }
        cout<<(flag?"Yes" : "No")<<endl;
    }
    return 0;
}

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZCAIHUI_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值