题目来源于 http://acm.wust.edu.cn/problem.php?id=1649&soj=0
★这题没有应用到二叉树,但是解出这题要对二叉树的遍历方式有深刻的理解qwq
相关知识:
1.二叉树前序遍历: 先访问根节点,再遍历左子树,最后遍历右子树。简单地说就是,先中再左后右
2.二叉树中序遍历: 先遍历根节点的左子树,再遍历根节点,最后遍历根节点的右子树。先左再中后右
3.二叉树后序遍历: 先遍历根节点的左子树,再遍历根节点的右子树,最后遍历根节点。先左再右后中
4.二叉树层序遍历: 先遍历最上面一层,逐渐往下遍历,层层从左到右一次遍历。从上到下,从左往右
以下图为例,图来自HDU 1710 http://acm.hdu.edu.cn/showproblem.php?pid=1710
前序遍历:1 2 4 7 3 5 8 9 6
中序遍历:4 7 2 1 8 5 9 3 6
后序遍历:7 4 2 8 9 5 6 3 1
层序遍历:1 2 3 4 5 6 7 8 9
思路:
我们已知前序和中序遍历,问题是怎么反推出后序遍历。就要抓住他们遍历的特点。还是以上图为例~
前序遍历的第一个一定是根节点,它在中序遍历中的位置将左右子树完美分隔开来。4 7 2是左,8 5 8 3 6是右
再分别以这两个小的二叉树重复此操作。
我是通过递归输出的,详见代码~
注意:
这两题都是求后序遍历,但是一个是数字形式一个是字母形式,所以操作起来会有一点小区别的。
因为数字要有一个空格隔开,字母没有。在HDU上面多有一个标记变量
代码:
WUSTOJ 代码如下
#include<bits/stdc++.h>
using namespace std;
char s1[105],s2[105];
void hhh(int a,int b,int n)
{
if(n==1) {cout<<s1[a]; return ;}
else if(n==0) return ;
int i;
for(i=0;s1[a]!=s2[b+i];i++);
hhh(a+1,b,i);
hhh(a+i+1,b+i+1,n-i-1);
cout<<s1[a];
}
int main()
{
while(cin>>s1>>s2){
int len=strlen(s1);
hhh(0,0,len);
cout<<endl;
}
}
HDU代码如下,注意多了一个flag标记变量
#include<stdio.h>
using namespace std;
int t1[1005],t2[1005];
void hhh(int a,int b,int n,int flag)
{
if(n==1) {printf("%d ",t1[a]); return ;}
else if(!n) return ;
int i;
for(i=0;t1[a]!=t2[b+i];i++);
hhh(a+1,b,i,0);
hhh(a+i+1,b+i+1,n-i-1,0);
if(flag) printf("%d",t1[a]);
else printf("%d ",t1[a]);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
int i;
for(i=1;i<=n;i++) scanf("%d",&t1[i]);
for(i=1;i<=n;i++) scanf("%d",&t2[i]);
hhh(1,1,n,1);
printf("\n");
}
return 0;
}