深入分析由前序和中序重构二叉树问题

原创 2015年07月10日 09:24:39

由下面的这棵树来分析
这里写图片描述
前序遍历:
ACFKDBUMWS
中序遍历:
KFDCAUBWMS

实际前序遍历的组成是
根节点+左边+右边
实际中序遍历的组成是
左边+根节点+右边

step1
前序遍历的第一个为根结点 ,所以A为根节点,
step2
在中序中找到A,分为两组
KFDC 根节点左边
UBWMS 根节点右边
而前序遍历中也可以分开了(只是顺序不一样,个数一样)
CFKD 是左边
BUMWS是右边
step 3
在左边CFKD重新作为一颗整树,重复步骤一和步骤二,根节点为C,
在中序中找到C,在分为左右边,

理论是可以实现重新构建一棵树,如何用编程语言实现?

采用一种递归方法
前序遍历
根+左+右
中序遍历
左+根+右

伪代码
struct node
{
char data;
struct node* left;
struct node* right;
}

struct node* creat(前序遍历字符串f,中序遍历字符串m)
{
struct node n;
n.data=从f中获取根;
fl=前序遍历根的左边;
fr=前序遍历根的右边;
ml=中序遍历根的左边;
mr=中序遍历根的右边;
n.left=creat(fl.ml);
n.right=creat(fr,mr);

return  n;

}

还有一个问题,递归的结束问题,什么时候结束。
以一个简单例子说明
前序遍历
ABC
中序遍历
BAC

根A+左B+右C
左B+根A+右C
进入creat函数后
f=“ABC”; m=“BAC”
fl=‘B’ ;fr=’C’
ml=’B’ ; mr=’C’
然后fl和ml进入递归
f=‘B’;m=‘B’
此时,就不再出现左子树和右子树了,很明显这个时候可以全身而退了。
左子树个数=0;
右子树个数=0;
说明左右子树都没有了这是就退

伪代码

struct node
{
    char data;
    struct node* left;
    struct node* right;
}

struct node* creat(前序遍历字符串f,中序遍历字符串m)
{
    struct node n;
    n.data=从f中获取根;
    fl=前序遍历根的左边;
    fr=前序遍历根的右边;
    ml=中序遍历根的左边;
    mr=中序遍历根的右边;
    if(左子树长度==0)
    {
         n.left=NULL;
    }
    else
         n.left=creat(fl.ml);
   if(右子树长度==0)
    {
        n.right=NULL;
    }
    else
    {
        n.right=creat(fr,mr);
    }

    return  n;
}

c代码实现

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

using namespace std;




typedef struct node
{
 char data;
 struct node* left;
 struct node* right;
}NODE;

//qian creat
NODE* creat_node(string &f,string &m)
{
 char c;
 string fl,fr;
 string ml,mr;
 int local;
 c=f[0];
 if(c>'Z' || c<'A')
 {
  cout<<"error data"<<endl;
  exit(-1);
 }

 local=m.find(c);
 if(local == -1)
 {
  cout<<"not find local"<<endl;
  exit(-1);
 }
 ml=m.substr(0,local);
 mr=m.substr(local+1,m.size()-1-local);
 fl=f.substr(1,ml.size());
 fr=f.substr(fl.size()+1,mr.size());

 NODE* node=new NODE;
 node->data  = c;

 if(local == 0)
  node->left = NULL;
 else
  node->left  = creat_node(fl,ml);
 if((m.size()-1-local)==0)
  node->right = NULL;
 else
  node->right = creat_node(fr,mr);
 return node;


}

void front_search(NODE* root)
{
 if(root == NULL)
  return;
 NODE node=*root;
 cout<<node.data;
 front_search(node.left);
 front_search(node.right);
}

void back_search(NODE* root)
{
 if(root == NULL)
 {
  return ;
 }
 NODE node = *root;
 back_search(node.left);
 back_search(node.right);
 cout<<node.data;
}
int main()
{
 string front;
 string mid;
 freopen("t.txt","r",stdin);
 NODE* head;
 if((head=new NODE)==NULL)
 {
  cout<<"new head error"<<endl;
  exit(-1);
 }

 getline(cin,front);
 getline(cin,mid);

 head=creat_node(front,mid);

 front_search(head);
 back_search(head);
 return 0;
}

这里写图片描述
这棵树重构成功

这个问题源于这样的小编程题目

题目
描述:
二叉树的前序、中序、后序遍历的定义:
前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。
题目类别: 树
难度: 中级
运行时间限制: 无限制
内存限制: 无限制
阶段: 入职前练习
输入:
两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C….最多26个结点。
输出:
输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。
样例输入:
ABC
BAC
FDXEAG
XDEFAG
样例输出:
BCA
XEDGAF

版权声明:本文为博主原创文章,未经博主允许不得转载。

剑指offer刷题之c++实现的根据二叉树的前序和中序遍历重建二叉树

#include "myHead.h" #include "allConstructBinaryTree.cpp" /* 利用前序和后序遍历,构造二叉树。 前序第一个节点就是根节点,然后根据这个节点...
  • u012270113
  • u012270113
  • 2015年08月08日 12:34
  • 967

根据前序和中序重建二叉树

注意:1、仅根据前序和后序无法构建唯一的二叉树;2、二叉树前序遍历,第一个数字总是树的根节点的值;3、中序遍历中,根节点的值在序列的中间,左子树的值子在根节点的值得左边,右字树的值在根节点的值得右边;...
  • dutsoft
  • dutsoft
  • 2014年05月21日 15:13
  • 942

根据前序和中序序列,建立二叉树(java实现)

根据前序序列:int[] preSort={1,2,4,7,3,5,6,8}; 中序序列:int[] inSort=new int[]{4,7,2,1,5,3,8,6}; 建立二叉树,求后序遍历等问题...
  • A784586
  • A784586
  • 2017年01月09日 18:13
  • 520

根据前序和中序构造二叉树-java版

package offer; class TreeNode{ public int value; public TreeNode left; public TreeNode right; pu...
  • huangcan0532
  • huangcan0532
  • 2015年07月06日 17:09
  • 620

剑指Offer面试题6重建二叉树(根据前序中序输出后序)

面试题6:重建二叉树。 输入二叉树的前序遍历和中序遍历结果,重建二叉树。假设输入的前序和中序结果都不含重复的数,例如:前序12473568,中序47215386,输出后序遍历结果。 思路:所谓前中...
  • login_sonata
  • login_sonata
  • 2017年02月26日 15:49
  • 224

根据前序和中序序列确定二叉树

方法1、确定树的根节点。树根是当前树中所有元素在前序遍历中最先出现的元素。 2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边...
  • luoluozlb
  • luoluozlb
  • 2016年08月08日 21:04
  • 2994

前序遍历和中序遍历构造二叉树[lintcode]

/** * Definition of TreeNode: * class TreeNode { * public: * int val; * TreeNode *left,...
  • xs_520
  • xs_520
  • 2017年08月05日 14:11
  • 196

二叉树知道前序中序或者中序后序求另外一个排列

二叉树的遍历: 前序遍历:根节点->左子树->右子树 中序遍历:左子树->根节点->右子树 后序遍历:左子树->右子树->根节点 求下面树的三种遍历:   ...
  • xyz5354
  • xyz5354
  • 2014年09月08日 22:46
  • 2021

二叉树前序,中序转后序

由二叉树的前序和中序如何得到二叉树的后序呢?要给出答案,首先得明白什么是前序、中序、后序。 二叉树前序:遍历顺序为,根节点、左子树、右子树;中序:遍历顺序为,左子树、根节点、右子树;后序:遍历顺...
  • wu_cai_
  • wu_cai_
  • 2016年09月17日 11:24
  • 515

二叉树前序、中序、后序遍历的相互求法

二叉树前序、中序、后序遍历的相互求法       二叉树是数据结构中常被问到的相关知识点,也是我们需要了解的一个知识点,那今天来总结一下二叉树的前序、中序、后序遍历的相互求法,即如果知道两个...
  • u014536527
  • u014536527
  • 2016年03月30日 02:45
  • 5266
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入分析由前序和中序重构二叉树问题
举报原因:
原因补充:

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