PTA Advanced 1159 Structure of a Binary Tree C++

目录

题目

Input Specification:

Output Specification:

Sample Input:

Sample Output:

思路

代码


题目

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 103 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

思路

这题也不是难题,可以在1167 Cartesian Tree 1020 Tree Traversals的基础上对dfs函数进行改进,即在dfs函数里面统计当前子树的根节点的信息,包括:层次(level)、双亲(parent)和左右孩子(left、right)

关键技术:

1. 如何获取statement中的数字 --- --- 用正则表达式做匹配

1164 Good in C这题中也用到了正则表达式匹配字符串,封装好的函数代码如下:

#include <regex>

// 根据传入的正则表达式分割字符串
// str-即将要进行分割的字符串;sep-正则表达式;result-存放分割后结果的容器 
void splitStringByRegex(string str,string sep,vector<int> &result){
	regex pattern(sep);
	sregex_token_iterator end;// 循环结束的标志 
	// 有-1时表示得到i是除正则表达式外的部分,没有-1时表示得到i是和正则表达式匹配的部分 
	for(sregex_token_iterator i(str.begin(),str.end(),pattern);i!=end;++i){ 
		result.push_back(stoi(*i));
	}
}

2. 如何判断statement是哪一类别 --- --- 用str1.find(str2)函数

// str1中找到了str2
if(str1.find(str2)!=string::npos){
	... ...
}else{
    // 没找到时
    ... ...
}

代码

#include <iostream>
#include <vector>
#include <string>
#include <regex>
#include <map>

using namespace std;

struct Node{
	int level;
	int parent;
	int left;
	int right;
};

vector<int> postOrder,inOrder;
map<int,Node> nodes;
int hasOneChildNum=0; 

// 根据传入的正则表达式分割字符串
// str-即将要进行分割的字符串;sep-正则表达式;result-存放分割后结果的容器 
void splitStringByRegex(string str,string sep,vector<int> &result){
	regex pattern(sep);
	sregex_token_iterator end;// 循环结束的标志 
	// 有-1时表示得到i是除正则表达式外的部分,没有-1时表示得到i是和正则表达式匹配的部分 
	for(sregex_token_iterator i(str.begin(),str.end(),pattern);i!=end;++i){ 
		result.push_back(stoi(*i));
	}
}

void dfs(int postLeft,int postRight, int inLeft,int inRight, int currentLevel, int parent){
	if(postLeft>postRight) return;
		
	// 当前子树的root是后序遍历序列的最后一个元素 
	int root=postOrder[postRight];
	
	// 确定root的level和parent 
	Node node; 
	node.level=currentLevel;
	node.parent=parent; 
	
	// 找到子树根在中序遍历序列中的位置
	int rootIndex=inLeft;
	for(;rootIndex<=inRight;rootIndex++)
		if(inOrder[rootIndex]==root) break;
	
	// 左子树后序遍历序列的index范围:postLeft ~ postLeft+rootIndex-inLeft-1
	int leftTreeLeft=postLeft;
	int leftTreeRight=postLeft+rootIndex-inLeft-1;
	// 右子树后序遍历序列的index范围:postLeft+rootIndex-inLeft ~ postRight-1
	int rightTreeLeft=postLeft+rootIndex-inLeft;
	int rightTreeRight=postRight-1;
	// 确定root的左右孩子
	if(leftTreeRight>=leftTreeLeft) node.left=postOrder[leftTreeRight];
	else node.left=-1;
	if(rightTreeRight>=rightTreeLeft) node.right=postOrder[rightTreeRight];
	else node.right=-1;
	
	// 统计只有一个孩子的结点的数量
	if(node.left!=-1&&node.right==-1||node.left==-1&&node.right!=-1) hasOneChildNum++;
	
	nodes[root]=node;
	
	dfs(leftTreeLeft,leftTreeRight, inLeft,rootIndex-1, currentLevel+1, root);// 该树的左子树相同操作 
	dfs(rightTreeLeft,rightTreeRight, rootIndex+1,inRight, currentLevel+1, root);// 该树的右子树相同操作 
}

int main(int argc, char** argv) {
	int n;
	cin>>n;
	
	postOrder.resize(n);
	inOrder.resize(n);
	for(int i=0;i<n;i++) cin>>postOrder[i];
	for(int i=0;i<n;i++) cin>>inOrder[i];
	
	// 根据后序和中序遍历次序健全结点信息 
	dfs(0,n-1, 0,n-1, 0, -1); 
	
	int m;
	cin>>m;
	cin.get();
	for(int i=0;i<m;i++){
		string statement; 
		getline(cin,statement);
		
		// 从statement中获取结点data 
		vector<int> nodeData;
		splitStringByRegex(statement,"[0-9]+",nodeData); 
		
		bool flag=false;
		// statement是判断某个结点是否是树的根时 
		if(statement.find("root")!=string::npos){
			if(nodes[nodeData[0]].parent==-1) flag=true;
		}else if(statement.find("level")!=string::npos){
			// statement是判断两个结点是否在同一层时
			if(nodes[nodeData[0]].level==nodes[nodeData[1]].level) flag=true;
		}else if(statement.find("parent")!=string::npos){
			// statement是判断结点0是否是结点1的双亲
			if(nodes[nodeData[1]].parent==nodeData[0]) flag=true;
		}else if(statement.find("left")!=string::npos){
			// statement是判断结点0是否是结点1的左孩子 
			if(nodes[nodeData[1]].left==nodeData[0]) flag=true;
		}else if(statement.find("right")!=string::npos){
			// statement是判断结点0是否是结点1的右孩子 
			if(nodes[nodeData[1]].right==nodeData[0]) flag=true;
		}else if(statement.find("siblings")!=string::npos){
			// statement是判断结点0和结点1是否是兄弟 
			int parent=nodes[nodeData[0]].parent;
			if(nodes[parent].left==nodeData[1]||nodes[parent].right==nodeData[1]) flag=true;
		}else if(statement.find("full")!=string::npos){
			// statement是判断这棵树是否是一颗full树 
			if(hasOneChildNum==0) flag=true;
		}
		
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值