团体程序设计天梯赛——L3-016 二叉搜索树的结构 (30 分)

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。(摘自百度百科)

给定一系列互不相等的整数,将它们顺次插入一棵初始为空的二叉搜索树,然后对结果树的结构进行描述。你需要能判断给定的描述是否正确。例如将{ 2 4 1 3 0 }插入后,得到一棵二叉搜索树,则陈述句如“2是树的根”、“1和4是兄弟结点”、“3和0在同一层上”(指自顶向下的深度相同)、“2是4的双亲结点”、“3是4的左孩子”都是正确的;而“4是2的左孩子”、“1和3是兄弟结点”都是不正确的。

输入格式:
输入在第一行给出一个正整数N(≤100),随后一行给出N个互不相同的整数,数字间以空格分隔,要求将之顺次插入一棵初始为空的二叉搜索树。之后给出一个正整数M(≤100),随后M行,每行给出一句待判断的陈述句。陈述句有以下6种:

A is the root,即"A是树的根";
A and B are siblings,即"A和B是兄弟结点";
A is the parent of B,即"A是B的双亲结点";
A is the left child of B,即"A是B的左孩子";
A is the right child of B,即"A是B的右孩子";
A and B are on the same level,即"A和B在同一层上"。
题目保证所有给定的整数都在整型范围内。

输出格式:
对每句陈述,如果正确则输出Yes,否则输出No,每句占一行。

输入样例:

5
2 4 1 3 0
8
2 is the root
1 and 4 are siblings
3 and 0 are on the same level
2 is the parent of 4
3 is the left child of 4
1 is the right child of 2
4 and 0 are on the same level
100 is the right child of 3

输出样例:

Yes
Yes
Yes
Yes
Yes
No
No
No

思路
昨天选拔赛忘了C++链表怎么建了,没申请空间,整了半天编译错误,唉
代码

#include<bits/stdc++.h>
using namespace std;
typedef struct stu *Tree;
struct stu{
	int x=0;
	Tree r=NULL;
	Tree l=NULL;
	int num;
};
Tree Build(int x,Tree T,int num){
	if(T==NULL){
		Tree T1=new stu;
		T1->x=x;
		
		T1->num=num;	
		T=T1;
	}else{
		if(x>T->x){
			T->r=Build(x,T->r,num+1);
		}else if(x<T->x){
			T->l=Build(x,T->l,num+1);
		}
	}
	return T;
}
Tree fun(Tree T,int x){
	while(T&&T->x!=x){
		if(x>T->x) T=T->r;
		else T=T->l;
	}
	return T;
}
int main(){
	int n,x;
	cin>>n;
	Tree T=NULL;	
	for(int i=0;i<n;i++){
		cin>>x;
		T=Build(x,T,1);
	}
	int m,a,b;
	string s,s1;
	cin>>m;
	getchar();
	for(int i=0;i<m;i++){
		int flag=0;
		getline(cin,s);
		if(s.find("root")!=s.npos){
			s1=s.substr(0,s.find(" "));
			a=stoi(s1);
			if(T&&T->x==a) flag=1; 
		}else if(s.find("siblings")!=s.npos){
			s1=s.substr(0,s.find(" "));
			a=stoi(s1);
			s1=s.substr(s.find("and")+4,s.find(" are")-s.find("and")-4);
			b=stoi(s1);
			Tree T2,T1=T;
			while(T1->x!=a&&T1){
				T2=T1;
				if(a>T1->x) T1=T1->r;
				else T1=T1->l;
			}
			if(T1&&T2->r&&T2->l&&(T2->r->x==a&&T2->l->x==b||T2->l->x==a&&T2->r->x==b))
			flag=1;
		}
		else if(s.find("parent")!=s.npos){
			s1=s.substr(0,s.find(" "));
			a=stoi(s1);
			s1=s.substr(s.find("of")+3);
			b=stoi(s1);
			Tree T1=fun(T,a);
			if(T1&&(T1->l&&T1->l->x==b||T1->r&&T1->r->x==b)) flag=1;
		}
		else if(s.find("left")!=s.npos){
			s1=s.substr(0,s.find(" "));
			a=stoi(s1);
			s1=s.substr(s.find("of")+3);
			b=stoi(s1);
			Tree T1=fun(T,b);
			if(T1&&T1->l&&T1->l->x==a) flag=1;
		}
		else if(s.find("right")!=s.npos){
			s1=s.substr(0,s.find(" "));
			a=stoi(s1);
			s1=s.substr(s.find("of")+3);
			b=stoi(s1);
			Tree T1=fun(T,b);
			if(T1&&T1->r&&T1->r->x==a) flag=1;
		
		}
		else if(s.find("level")!=s.npos){//同一层 
			s1=s.substr(0,s.find(" "));
			a=stoi(s1);
			s1=s.substr(s.find("and")+4,s.find(" are")-s.find("and")-4);
			b=stoi(s1);
			Tree T1=fun(T,a);
			Tree T2=fun(T,b);
			if(T1&&T2&&T1->num==T2->num) flag=1;
		}
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}

网上搜到了更简便的写法
【CCCC】L3-016 二叉搜索树的结构 (30分),,手动建堆(二叉搜索树节点询问),map写法
代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	int l=-1;
	int r=-1;
	int fa=-1;//双亲节点 
	int h;//高度 
};
map<int,node> Tree;
void insert(int root,int h,int x){
	if(root==-1) return;
	int rr=x<root?Tree[root].l:Tree[root].r;
	if(rr==-1){
		if(x<root) Tree[root].l=x;
		else Tree[root].r=x;
		Tree[x].fa=root;
		Tree[x].h=h;
	}
	else insert(rr,h+1,x);
}
int Judge(int root,int a,int b,string s1){
	if(s1=="root") return a==root;//这个判断必须在find前面,因为该树可能只有一个节点 
	if(Tree.find(a)==Tree.end()||Tree.find(b)==Tree.end()) return 0;
	else if(s1=="siblings") return Tree[a].fa==Tree[b].fa;
	else if(s1=="parent") return Tree[b].fa==a;
	else if(s1=="level") return Tree[a].h==Tree[b].h;
	else if(s1=="left") return Tree[b].l==a;
	else if(s1=="right") return Tree[b].r==a;
}
int main(){
	int n,root,t;
	cin>>n>>root;
	for(int i=2;i<=n;i++){
		cin>>t;
		insert(root,1,t);
	}
	int m,a=0,b=0;
	cin>>m;
	for(int i=0;i<m;i++){
		string s,s1;
		cin>>a;
		getchar();
		getline(cin,s);
		if(s.find("root")!=s.npos) s1="root";
		else if(s.find("siblings")!=s.npos){
			s1=s.substr(4,s.find("are")-4);
			b=stoi(s1);
			s1="siblings";
		}
		else if(s.find("parent")!=s.npos){
			s1=s.substr(s.find("of")+3);
			b=stoi(s1);
			s1="parent";
		}
		else if(s.find("left")!=s.npos){
			s1=s.substr(s.find("of")+3);
			b=stoi(s1);
			s1="left";
		}
		else if(s.find("right")!=s.npos){
			s1=s.substr(s.find("of")+3);
			b=stoi(s1);
			s1="right";
		}
		else if(s.find("level")!=s.npos){
			s1=s.substr(4,s.find("are")-4);
			b=stoi(s1);
			s1="level";
		}
		if(Judge(root,a,b,s1)) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值