根据先序遍历和中序遍历建立二叉树

title: 根据先序遍历和中序遍历建立二叉树
date: 2019-07-23 22:37:34
tags: 数据结构

问题

已知一棵二叉树的先序遍历以及中序遍历,重建二叉树。二叉树的每一个节点有三个属性,左子节点,右子节点,以及节点值。

思路

先序遍历服从规则“根左右”,所以由此可知,对于一个先序遍历得到的数组,第一个元素一定是根节点

中序遍历服从规则”左根右“,所以由此可知,对于一个中序遍历得到的数组,根节点左边的元素都属于根节点的左子树,而根节点右边的元素都属于根节点的右子树

所以,我们可以先通过先序遍历的第一个元素确定根节点,然后通过中序遍历结合根节点,获得当前根节点的左右子树,再将子树看成一棵独立的树,继续使用先序遍历判断根节点,中序遍历判断子树的方式,最终建立起整棵树;

例子

假设有一棵二叉树,先序遍历为{1,2,4,7,3,5,6,8},中序遍历为{4,7,2,1,5,3,8,6},则建树过程如下:

首先,通过先序遍历可知树的根节点为1,则在中序遍历中,1左边的元素4,7,2即为根的左子树的元素,而1右边的元素5,3,8,6即为根节点的右子树;

对于左子树4,7,2来说,在先序遍历中,这三个点的顺序为2,4,7,则2为根节点,而在中序遍历中,4,7均在2的左边,则4,7均为以2为根树的左子树,且没有右子树;

对于4,7这两个节点来说,先序遍历中,4节点在7节点之前,所以4为根节点,而7作为子树,在中序遍历中,74之后,所以7为右子树;

对于根节点1的右子树5,3,8,6来说,在先序遍历中,3在最前面,所以3为这棵子树的根节点,而在中序遍历中,53的左边,所以属于左子树,而8,63的右边,属于右子树;

对于根节点3的右子树8,6,在先序遍历中,68之前,所以,6又为根节点,而在中序遍历中,86的左边,所以86的左子节点;

至此,二叉树便重建完成;

代码

树的节点

1 public class TreeNode {
2     int val;        //当前节点的值
3     TreeNode left;    //左子节点
4     TreeNode right;    //右子节点
5
6     TreeNode(int x) {
7         val = x;
8     }
9 }

建树方法

 1 /**
 2 * pre:线序遍历得到的数组
 3 * in:中序遍历得到的数组
 4 */
 5 public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
 6     if(pre.length == 0) {
 7         return null;
 8     }
 9
10     int root = pre[0];
11     TreeNode node = new TreeNode(root);
12
13     //寻找根节点在in中的索引
14     int i = 0;
15     for( ; i<in.length; ++i) {
16         if(in[i] == root) {
17             break;
18         }
19     }
20
21     //建立左子树
22     int[] leftIn = Arrays.copyOfRange(in, 0, i);
23     int[] leftPre = Arrays.copyOfRange(pre, 1, i+1);
24     node.left = reConstructBinaryTree(leftPre, leftIn);
25
26     //建立右子树
27     int[] rightIn = Arrays.copyOfRange(in, i+1, in.length);
28     int[] rightPre = Arrays.copyOfRange(pre, i+1, pre.length);
29     node.right = reConstructBinaryTree(rightPre, rightIn);
30
31     return node;
32 }
 

建树代码(优化)

 1 public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
 2     return getRootTreeNode(pre, 0, pre.length-1, in, 0, in.length-1);
 3 }
 4
 5 /**
 6 * preL:当前子树在先序遍历的数组中的起始下标
 7 * preR:当前子树在先序遍历的数组中的结束下标
 8 * inL:当前子树在中序遍历的数组中的起始下标
 9 * inR:当前子树在中序遍历的数组中的起始下标
10 */
11 public TreeNode getRootTreeNode(int[] pre, int preL,
12                                 int preR, int[] in, int inL, int inR) {
13     if(preL > preR) {
14         return null;
15     }
16
17     TreeNode node = new TreeNode(pre[preL]);
18
19     for(int i=inL; i<=inR; ++i) {
20         if(in[i] == pre[preL]) {
21
22             node.left = getRootTreeNode(pre, preL+1, preL+i-inL, in, inL, i-1);
23             node.right = getRootTreeNode(pre, preL+i-inL+1, preR, in, i+1, inR);
24             break;
25         }
26     }
27
28     return node;
29 }

原文地址:https://www.cnblogs.com/tuyang1129/p/11235173.html

时间: 2024-11-10 01:13:29

根据先序遍历和中序遍历建立二叉树的相关文章

算法学习 - 表达树的建立(后缀表达式法),树的先序遍历,中序遍历,后序遍历

表达树就是根据后缀表达式来建立一个二叉树. 这个二叉树的每个叶子节点就是数,真祖先都是操作符. 通过栈来建立的,所以这里也会有很多栈的操作. 树的先序遍历,中序遍历,后序遍历的概念我就不讲了,不会的自行百度,不然也看不懂我的代码. 下面是代码: // // main.cpp // expressionTree // // Created by Alps on 14-7-29. // Copyright (c) 2014年 chen. All rights reserved. // #includ

根据二叉树的前序遍历和中序遍历重建二叉树

题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 1 /** 2 * Definition for binary tree 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(

二叉查找树的前序遍历,后序遍历和中序遍历互求算法模板

面试的痛 前几天去阿里面试,一时忘记了二叉树的前序遍历中序遍历和后序遍历的概念,已经想死了. 然后最近去腾讯面试,被问到怎么已知前序遍历/后序遍历 + 中序遍历,求后序遍历/前序遍历,看来这种问题很喜欢考. 其实这个问题想清楚了很简单,只要把这三个概念理解透彻就可以做出来了,比如前序遍历的第一个值一定是根节点,然后这个根节点对应到中序遍历里面,在中序遍历的这个值的两边的值,一定在以此节点为根节点的两个子树上,同理,后序遍历也一样. 已知前序遍历和后序遍历是不能求唯一的中序遍历树的. #inclu

已知二叉树的前序遍历、中序遍历或者中序遍历、后序遍历求二叉树结构的算法

二叉树中的前序遍历是先访问根结点,再访问左子树,右子树. 中序遍历是先访问左子树,再是根结点,最后是右子树. 后序遍历是先访问左子树,再是右子树,最后是根结点. 算法思路是先根据前序遍历的第一个结点或者后序遍历的最后一个结点,查找对应在中序遍历中的位置,就可以确定左子树包含的元素和右子树包含的元素,最后通过递归来实现就可以了. 二叉树的表示形式为 //二叉树的结构表示为 class TreeNode { int val; TreeNode left; TreeNode right; TreeNo

根据前序遍历和中序遍历求后序遍历

根据前序遍历和中序遍历求后序遍历 一道HULU的笔试题(How I wish yesterday once more) 假设有棵树,长下面这个样子,它的前序遍历,中序遍历,后续遍历都很容易知道. PreOrder:         GDAFEMHZ InOrder:            ADEFGHMZ PostOrder:       AEFDHZMG 现在,假设仅仅知道前序和中序遍历,如何求后序遍历呢?比如,已知一棵树的前序遍历是"GDAFEMHZ",而中序遍历是"AD

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

问题描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 思路: 在二叉树的前序遍历序列中,第一个数字总是树的根结点的值.但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边.因此我们需要扫描中序遍历序列,才能找到根结点的值. 如下图所示,

前序遍历和中序遍历重建二叉树

对于二叉树,在此我不做过多讲解,如有不懂,请参照一下链接点击打开链接 1.在此二叉树的定义: struct BinaryTreeNode     {         BinaryTreeNode<T> *_Left;         BinaryTreeNode<T> *_Right;         T _data;     public:         BinaryTreeNode(const T& x)             :_Left(NULL)       

已知二叉树的先序遍历和中序遍历序列求后序遍历序列

package algorithm01; import java.util.Scanner; /** * 给出先序遍历和中序遍历序列求出二叉树的后续遍历序列 * @author wxisme * */ public class ToReverse { public static void main(String[] args) { Scanner scan = new Scanner(System.in); String s1, s2; while(scan.hasNext()) { s1 =

已知二叉树的前序遍历和中序遍历,如何得到它的后序遍历?

对一棵二叉树进行遍历,我们可以采取3中顺序进行遍历,分别是前序遍历.中序遍历和后序遍历.这三种方式是以访问父节点的顺序来进行命名的.假设父节点是N,左节点是L,右节点是R,那么对应的访问遍历顺序如下: 前序遍历    N->L->R 中序遍历    L->N->R 后序遍历    L->R->N /***************************************************************************************

027依据前序遍历和中序遍历,重建二叉树(keep it up)

剑指offer中题目:http://ac.jobdu.com/problem.php?pid=1385 题目描写叙述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.如果输入的前序遍历和中序遍历的结果中都不含反复的数字. 比如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列. 输入: 输入可能包括多个測试例子,对于每一个測试案例, 输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点