PTA中三道已知树的中序遍历与前(后)序遍历求二叉树问题的链接:
目前我们给出了三道pta中的习题,通过这三道题我们回顾一下已知树的中序遍历与前(后)序遍历求二叉树的相关问题。
首先我们来看第一道题:
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
我们首先需要知道,后序遍历的最后一个结点就是二叉树的根结点。而中序遍历中,根结点左边的就是左子树,右边的就是右子树。所以我们很快就可以从输入样例中得出4是根结点,123是左子树的结点,共3个结点,567是右子树的结点,共三个结点。
我们又知道,后序遍历先遍历左子树,后遍历右子树,所以根结点前面的3个结点576是右子树上的,剩下的231是左子树上的。这时就是一个递归定义的内容了,我们可以看出1是左子树的根结点,6是右子树的根结点…
这时我们已经给出了如何根据后序遍历和中序遍历求二叉树的思想,因为本人知识水平有限,就不再过多阐述。
下面附上这道题的代码:
#include
#include
typedef struct node* bintree;
typedef struct node{
bintree left;
bintree right;
int data;
}tree;
bintree creat(int n,int a[],int b[]){
bintree p;
int i;
if(n==0){
return NULL;//如果需要构造的二叉树结点数为0,返回NULL
}else{
//否则开始构造二叉树
p=(bintree)malloc(sizeof(tree));//为结点申请空间
p->data=a[n-1];//将后序遍历数组最后一个数的值赋给根结点
for(i=0;i<n;i++){
if(a[n-1]==b[i]){
//找到根结点在中序遍历的位置
break;
}
}
//左子树共有i个结点,右子树共有n-1-i个结点。
//左子树的后序遍历数组为last[0]-[i-1],中序遍历数组为mid[0]-[i-1]
//右子树的后序遍历数组为last[i]-[n-1],中序遍历数组为mid[i+1]-[n-1]
p->left=creat(i,a,b);
p->right=creat(n-1-i,a+i,b+i+1);
}
return p;
}
void pp(bintree bt){
int front=0,rear=1;
bintree p=bt,t[60];
//这块队列的数组尽量开大一点,因为本身数据量不大,我们就偷个懒
t[0]=bt;
while(front<rear){
if(t[front]!=NULL){
p=t[front];
if(p==bt){
printf("%d",t[front]->data);
}else{
//此处注意输出格式
printf(" %d",t[front]->data);
}
t[rear++]=p->left;
t[rear++]=p->right;
}
front++;
}//借用队列实现层序遍历
}
int main(){
bintree a;
int n,last[30],mid[30],i,j;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&last[i]);
}
for(i=0;i<n;i++){
scanf("%d",&mid[i]);
}
a=creat(n,last,mid);
pp(a);
return 0;
}
接着我们来看第二道题:
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
输出样例:
4 6 1 7 5 3 2
和上面的题目是一个意思,我们先给出几个已知结论:
前序遍历数组的第一个数是根结点的值,在中序遍历中找到根结点所在位置i后我们就知道左右子树的结点数分别是 i 和 n-1-i。那么前序遍历数组pre[1]-[i]就是左子树的前序遍历,前序遍历数组pre[i+1]-[n-1]就是右子树的前序遍历。我们自然可以得知pre[1]是左子树的根结点,pre[i+1]是右子树的根结点,这也是个用递归可以解决的问题。
下面附上代码:
#include
#include
typedef struct node* bintree;
typedef struct node{
bintree left;
bintree right;
int data;
}tree;
bintree create(int n,int *pre,int *mid){
//a前序遍历 b中序遍历
bintree p;
int i;
if(n==0){
return NULL;
}else{
p=(bintree)malloc(sizeof(tree));
p->data=pre[0];
for(i=0;i<n;i++){
if(mid[i]==pre[0]){
break;
}
}
p->left=create(i,pre+1,mid);
p->right=create(n-1-i,pre+1+i,mid+i+1);
}
return p;
}
void jx(bintree bt){
//这里的镜像也是一个很简单的递归函数
bintree p;
if(bt!=NULL){
if(bt->left!=NULL || bt->right!=NULL){
p=bt->right;
bt->right=bt->left;
bt->left=p;
}
}else{
return;
}
jx(bt->left);
jx(bt->right);
}
void pp(bintree bt){
int front=0,rear=1;
bintree t[60];
t[0]=bt;
while(front<rear){
if(t[front]!=NULL){
if(t[front]==bt){
printf("%d",t[front]->data);
}else{
printf(" %d",t[front]->data);
}
t[rear++]=t[front]->left;
t[rear++]=t[front]->right;
}
front++;
}
}
int main(){
int n,pre[30],mid[30],i;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&mid[i]);
}
for(i=0;i<n;i++){
scanf("%d",&pre[i]);
}
bintree bt;
bt=create(n,pre,mid);
jx(bt);
pp(bt);
return 0;
}
下面看最后一道题:
给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。
输入格式:
输入首先给出正整数N(≤50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。
输出格式:
输出为一个整数,即该二叉树的高度。
输入样例:
9
ABDFGHIEC
FDHGIBEAC
输出样例:
5
直接附上代码,怎么做的思想已经在上文阐述过了,这里唯一一个需要注意的点就是求二叉树的高度,这也是一个递归函数,不难看懂源码。
#include
#include
typedef struct node* bintree;
struct node{
bintree l;
bintree r;
char data;
};
bintree createbintree(char a[],char b[],int n){
bintree bt;
int i;
if(n==0){
return NULL;
}else{
bt=(bintree)malloc(sizeof(struct node));
bt->data=a[0];
for(i=0;i<n;i++){
if(b[i]==a[0])break;
}
bt->l=createbintree(a+1,b,i);
bt->r=createbintree(a+i+1,b+i+1,n-i-1);
}
return bt;
}
int gettree(bintree bt){
int hr,hl,h;
if(bt==NULL){
return 0;
}else{
hl=gettree(bt->l);
hr=gettree(bt->r);
if(hl<hr){
hl=hr;
}
h=hl;
h++;
}
return h;
}
int main(){
int n,i;
scanf("%d",&n);
char f1[n],f2[n];
scanf("%s",f1);
scanf("%s",f2);
bintree bt=createbintree(f1,f2,n);
printf("%d",gettree(bt));
}