23.1.7

1.

农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。

你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:

         C
         /  \
        /  \
       B    G
      / \  /
       A   D  H
        / \
       E   F

树的中序遍历是按照左子树,根,右子树的顺序访问节点。

树的前序遍历是按照根,左子树,右子树的顺序访问节点。

树的后序遍历是按照左子树,右子树,根的顺序访问节点。

输入格式

第一行: 树的中序遍历

第二行: 同样的树的前序遍历

输出格式

单独的一行表示该树的后序遍历。

输入输出样例

输入 #1复制

ABEDFCHG
CBADEFGH 

输出 #1复制

AEFDBHGC

说明/提示

题目翻译来自NOCOW。

USACO Training Section 3.4

思路的话,这个题的话已知中序和前序求后续,二叉树有个特点,前序遍历的第一个字母就是根节点,后面的话谁先出现谁就是根节点,然后就好办了,先在中序中找到先序中相同的节点然后再分别处理左子树和右子树,然后输出相同的节点即可。

#include<stdio.h>
#include<string.h>
char a[30],b[30],c[30];
int e,m;
void f(int x,int y,int l,int r)
{
	if(x>y||l>r){
		return ;
	}
    for(int i=0;i<e;i++){
		if(a[i]==b[l]){
			f(x,i-1,l+1,l+i-x);
			f(i+1,y,l+i+1-x,r);
			printf("%c",a[i]);
		}
	}
	
}
int main()
{
	scanf("%s",a);
	scanf("%s",b);
	e=strlen(a);
	f(0,e,0,e);
return 0;
}

2.

输入一串二叉树,输出其前序遍历。

输入格式

第一行为二叉树的节点数 nn。(1 \leq n \leq 261≤n≤26)

后面 nn 行,每一个字母为节点,后两个字母分别为其左右儿子。特别地,数据保证第一行读入的节点必为根节点。

空节点用 * 表示

输出格式

二叉树的前序遍历。

输入输出样例

输入 #1复制

6
abc
bdi
cj*
d**
i**
j**

输出 #1复制

abdicj

思路如下,先看这个题的话第一行第一个结点肯定是根节点后面两个是左子树和右子树,然后需要判断每个节点后面是不是*,然后判断是否找出那个节点,然后分别处理左子树和右子树,然后输出节点就好。

#include<stdio.h>
#include<string.h>
char a[30][3],x;
int n,i,j;
void f(char x)
{
	if(x!='*'){
    printf("%c",x);
    for(int i=1;i<=n;i++){
		if(a[i][0]==x){
			f(a[i][1]);
			f(a[i][2]);
		}
	}
	}	
	return ;	
}
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%s",a[i]);
	}
    f(a[1][0]);
return 0;
}

3.

给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,且二叉树的节点个数 \le 8≤8)。

输入格式

共两行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。

输出格式

共一行一个字符串,表示一棵二叉树的先序。

输入输出样例

输入 #1复制

BADC
BDCA

输出 #1复制

ABCD

说明/提示

【题目来源】

NOIP 2001 普及组第三题

思路的话,跟第一题正好相反,这个是已知中序和后序,输入的时候要注意最好使用字符串输入,

然后需要注意的是需要找出从后序排列的最后一个开始找,然后正常处理左子树和右子树就好了,但是需要判断是否是左子树还是右子树。

#include<stdio.h>
#include<string.h>
char a[30],b[30],c[30];
int e,m;
void f(int x,int y,int l,int r)
{
	if(x>y||l>r){
		return ;
	}
    for(int i=0;i<e;i++){
		if(a[i]==b[r]){
			printf("%c",b[r]);
			if(i>x){f(x,i-1,l,r-y+i-1);}
			if(i<y){f(i+1,y,l+i-x,r-1);}
		}
	}
	
}
int main()
{
	scanf("%s",a);
	scanf("%s",b);
	e=strlen(a);
	f(0,e-1,0,e-1);
return 0;
}

4.

我们都很熟悉二叉树的前序、中序、后序遍历,在数据结构中常提出这样的问题:已知一棵二叉树的前序和中序遍历,求它的后序遍历,相应的,已知一棵二叉树的后序遍历和中序遍历序列你也能求出它的前序遍历。然而给定一棵二叉树的前序和后序遍历,你却不能确定其中序遍历序列,考虑如下图中的几棵二叉树:

所有这些二叉树都有着相同的前序遍历和后序遍历,但中序遍历却不相同。

输入格式

输A数据共两行,第一行表示该二叉树的前序遍历结果s1,第二行表示该二叉树的后序遍历结果s2。

输出格式

输出可能的中序遍历序列的总数,结果不超过长整型数。

输入输出样例

输入 #1复制

abc                           
cba

输出 #1复制

4

说明/提示

无提示

思路的话就是要找到单独的子节点,因为如果A的子节点是B的话那么B的父节点就只能是A了,所以这题的话就是主要要找单独的子节点个数。

#include<stdio.h>
#include<string.h>
char a[10000],b[10000];
int n=1,m;
int main()
{
	scanf("%s\n%s",a,b);
	for(int i=0;i<strlen(a);i++){
		for(int j=1;j<strlen(b);j++){
			if(a[i]==b[j]&&a[i+1]==b[j-1]){
				m++;
			}
		}
	}
	for(int i=m;i>0;i--){
		n=n*2;
	}
	printf("%d",n);
	
	
	
	
	
return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值