已知先序和中序求后序或中序和后序求先序

原创 2015年11月19日 18:48:22
首先介绍树的三种遍历方式的遍历顺序:
先序遍历:根、左子树、右子树(特点:第一个元素为根)
中序遍历:左子树、根、右子树(特点:根的两边分别为左子树和右子树)
后序遍历:左子树、右子树、根(特点:最后一个元素为根)
有如下图的二叉树:


其先序、中序、后序遍历分别为:DBACEGF、ABCDEFG、ACBFGED。
1、已知先序和中序求后序
先序遍历的第一个字符为根,因此只需在中序遍历中找到它,就可以把根节点的左子树和右子树分开,就可以知道左子树的字符个数和右子树的字符个数,然后可以确定先序遍历中哪部分是左子树,哪部分是右子树,之后递归先序遍历的序列,直到结束。
如上面的例子:先序遍历的第一个字符是D,则根节点为D,从中序遍历中可以找到D的位置,左边的ABC即为左子树的字符,右边的EFG即为右子树的字符,如果开始递归函数为:build("DBACEGF"),则找到根的位置后,可以分为递归左子树的先序遍历和递归右子树的先序遍历:build("BAC")和build("EFG"),其对应的中序遍历为:ABC和EFG。然后继续进行以上步骤,直到找完先序序列。每找到根就可以直接输出或保存到数组中,需要注意的是递归的时候不要把根包含在内。
代码如下:

  //已知先序和中序求后序

方法一:

#include<stdio.h>
#include <cstring>
char a[27],b[27];//存先序遍历和中序遍历
void fun(int ab, int ae, int bb, int be)
{//四个参数分别为:先序遍历的起始位置和结束位置和中序遍历的起始位置和结束位置
    int i;
    if(ab>ae)//如果已经到达叶子,返回
        return;
    for(i=bb; b[i]!=a[ab]; ++i);//找到根节点在中序遍历中的位置
    fun(ab+1, ae-be+i, bb, i-1);//递归求左子树的后序遍历,ab+1是指把根去掉之后的位置
    fun(ae-be+i+1, ae, i+1, be);//递归求右子树的后序遍历
    putchar(a[ab]);//在递归结束后输出根
}
int main()
{
    int i;
    while(scanf("%s%s", a, b) != EOF)
    {
        int len = strlen(a);
        fun(0, len-1, 0, len-1);
        puts("");
    }
}

其中ae-be+i是ae-(be-i),be-i是右子树的长度,ae-(be-i)即是先序遍历中左子树的结束位置,递归右子树同理。

方法二:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void build(int n,char *s1,char *s2,char *s){
if(n<=0) return;
int p=strchr(s2,s1[0])-s2;
build(p,s1+1,s2,s);
build(n-p-1,s1+p+1,s2+p+1,s+p);
s[n-1]=s1[0];
}
int main(){
char s1[30],s2[30],s[30];
while(cin >> s1 >> s2){
int n=strlen(s1);
build(n,s1,s2,s);
s[n]='\0';
printf("%s\n",s);
}
return 0;
}

2、已知中序和后序求先序

后序序列的特点是最后一个是根,道理与已知先序和中序求后序一样,同样是递归,只是需要改变几个参数。附上代码和注释。

方法一:

#include<stdio.h>
#include <cstring>
char a[27],b[27];
void fun(int ab, int ae, int bb, int be)
{
    int i;
    if(ab>ae)
        return;
    putchar(a[ae]);//由于是求先序遍历,所以要先输出根节点
    for(i=bb; b[i]!=a[ae]; ++i);//对应的,后序序列的最后一个为根,所以根为a[ae]
    fun(ab, ae-be+i-1, bb, i-1);//递归求左子树的先序遍历
    fun(ae-be+i, ae-1, i+1, be);//递归求右子树的先序遍历,ae-1为去掉根后的位置
}
int main()
{
    int i;
    while(scanf("%s%s", a, b) != EOF)
    {
        int len = strlen(a);
        fun(0, len-1, 0, len-1);
        puts("");

    }

}

方法二:



#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int k;
void build(int n,char *s1,char *s2,char *s){
if(n<=0) return;
s[k++]=s1[n-1];
int p=strchr(s2,s1[n-1])-s2;
build(p,s1,s2,s);
build(n-p-1,s1+p,s2+p+1,s);
}
int main(){
char s1[30],s2[30],s[30];
while(cin >> s1 >> s2){
int n=strlen(s1);
    k=0;
build(n,s1,s2,s);
s[n]='\0';
printf("%s\n",s);
}
return 0;
}

 

在以上程序中,给函数传递了四个参数,分别代表起始和结束位置,其实可以只需要三个参数即可,因为中序遍历的起始位置可以通过另外一个序列的长度来找到,所以只需要ab、ae、be即可。
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

已知中序排列和后序排列求先序排列

Name: 已知先后序和中序,求出它的先序排列   Copyright: 始发于goal00001111的专栏;允许自由转载,但必须注明作者和出处   Author: goal00001111 ...

已知二叉树先序序列和中序序列,求后序序列

回答了百度知道上的一个提问,原题是这样的: 当一棵二叉树前序序列和中序序列分别为HGEDBFCA和EGBDHFAC时,其后序序列为什么?当一棵二叉树前序序列和中序序列分别为HGEDBFCA和EGBDH...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

Binary Tree Traversals 已知先序 中序 求后序

Binary Tree Traversals 纯属个人理解 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/3276...

二叉树——已知二叉树先序,建树,并输出中序、后序,并求树叶数和深度

Description        已知一个按先序序列输入的字符序列,如abc,,de,g,,f,,,(其中逗号表示空节点)。请建立二叉树并按中序和后序方式遍历二叉树,最后求出叶子节点个数和二叉树...

二叉树已知先序&中序求后序

#pragma once #include using namespace std; //************************** 先序&中序==>>后序 *************...

C++ 二叉树中已知先序中序求后序的递归方法

#include using namespace std; const int MaxSize=20; //数组的最大尺寸 int p; //一个临时的数字用来标记当前操作的数组的位置 ...

NYOJ221二叉树重建(已知先序和中序求后序)

题意:大概意思就是给你一个二叉树的先序遍历和中序遍历,然后需要你求出后序遍历并输出到屏幕上面   思路分析: 首先明确三种遍历的特点: 先序遍历:先访问根节点,接着访问左子树,再访问右子树,由此...

二叉树的三种遍历的相互转化——已知先序中序求后序

题目: 已知二叉树的先序和中序遍历字符串,编程实现输出后序遍历字符串, 如果没有成功输出Failed,最后分析时间和空间复杂度。 题目来源: 经典题目,也是网易游戏2011年游戏开发工...

二叉树:已知先序和中序求后序

采用了递归的思想来解决问题。 先序遍历的第一个结点为该二叉树的根节点。 找到中序遍历中该根节点所在位置,则根节点左侧为该二叉树的左子树的中序遍历(右侧为二叉树的右子树的中序遍历),我们同时也得到了...

已知二叉树的后序和中序排列,求先序排列再线索化的问题(笔试常考)

今天参加暑期实习笔试,碰到这道题:二叉树的后序排列DBEFCA,中序排列DBAECF,那么对其做先序线索化二叉树,节点E的线索化指向节点?
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)