根据中序和前序序列来构造二叉树,以宽度优先遍历输出



/**
 * 重建二叉树 ;根据给定的前序和中序遍历的结果,构造出树的结构
 */
package binaryBree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * @author Amory.Wang
 * Question : 重建二叉树
 * test example : 普通二叉树 , 特殊二叉树(只有右结点或者只有左结点) ,特殊输入测试 : root=null/输入前序和中序不匹配
 * 2017年7月28日下午4:27:15
 */

class node{
    int data;
    node leftChild;
    node rightChild;

    /**
     * allocate new tree node
     */
    public node(int d) {
        this.data = d;
        this.leftChild = null;
        this.rightChild = null;
    }
}

public class ReconstructTree{
    public static node returnTree(){

        System.out.println("input the preOrder : (please use ‘,‘)");
        Scanner scan = new Scanner(System.in);
        String s = scan.next();
        String[] sa = s.split(",");
        int[] preOrder = new int[sa.length];
        for(int i=0; i<preOrder.length; ++i){
            preOrder[i] = Integer.parseInt(sa[i]);
        }

        System.out.println("input the inOrder : ");
        String s1 = scan.next();
        String[] sa1 = s1.split(",");
        int[] inOrder = new int[sa1.length];
        for(int i=0; i<inOrder.length; ++i){
            inOrder[i] = Integer.parseInt(sa1[i]);
        }

        if(preOrder.length != inOrder.length){
            System.out.println("preOrder‘s number is not equals inOrder‘s number");
            return null;
        }
        return constructCore(preOrder, 0, preOrder.length-1, inOrder, 0, inOrder.length-1);

    }

    /**
     *
     * @param pre : 前序遍历的数组
     * @param in : 中序遍历的数组
     * @param startPre : 前序的开始节点位置
     * @param endPre : 前序的结束节点
     * @param startIn : 中序的开始节点位置
     * @param endIn : 中序的结束节点位置
     * @return : 根节点
     */
    public static node constructCore(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn){
        if(pre == null || in == null){
            System.out.println("root is null !");
            return null;
        }

        // step 1 : 找到前序的根节点在中序的索引
        node root = new node(pre[startPre]);
        int rootInindex = startIn;
        while(root.data != in[rootInindex]){
            rootInindex ++;
        }
        // prepare : 1-1 : 确定左右子树的个数
        int leftNodes = rootInindex-startIn;
        int rightNodes = endIn-rootInindex;
        // 1-2 : 在前序中根据左右子树的个数确定左右子树的节点分别是哪些
        int startLeft = startPre+1;
        int endLeft = startLeft+leftNodes-1;
        int startRight = endLeft+1;
        int endRight = startRight+rightNodes-1;

        // step 2 : 对于中序中的根节点的位置在结合前序序列中进行左右子树的创建
        if(leftNodes <= 0){
            // 左子树为空
            root.leftChild = null;
        }else{

            root.leftChild = constructCore(pre, startLeft, endLeft, in, startIn, rootInindex-1);
        }
        if(rightNodes <= 0){
            // 右子树为空
            root.rightChild = null;
        }else{
            root.rightChild = constructCore(pre, startRight, endRight, in, rootInindex+1, endIn);
        }
        return root;
    }

    // step 3 : 进行宽度优先遍历  -- 要用到队列的特征,先进先出

    public static StringBuilder borderPrintTree(node root){
        StringBuilder widthString = new StringBuilder();
        Queue<node> nodeQue = new LinkedList<node>();
        if(root != null){
            nodeQue.add(root);
        }
        while(!nodeQue.isEmpty()){
            node popNode = nodeQue.poll();
            widthString.append(popNode.data);
            if(popNode.leftChild != null){
                nodeQue.add(popNode.leftChild);
            }
            if(popNode.rightChild != null){
                nodeQue.add(popNode.rightChild);
            }
        }
        return widthString;
    }

    // test
    public static void main(String[] args) {
        node root = returnTree();
        StringBuilder sb = borderPrintTree(root);
        System.out.println(sb);
    }

}

总结一下 : 这个递归的过程是逐渐优化的过程,容易搞混的地方主要在于对于前序序列和中序序列的中的参数变化,所以一点很重要,每一步的目的是什么,需要哪些参数来满足需求,搞清楚了之后在写代码.

时间: 2024-08-12 20:13:58

根据中序和前序序列来构造二叉树,以宽度优先遍历输出的相关文章

通过树的先序和中序遍历序列来构造二叉树

题目:给出一棵二叉树的先序和中序遍历的序列,构造出该二叉树. 思路一:采用分治法. 1)取先序遍历序列的第一个值,用该值构造根结点,,然后在中序遍历序列中查找与该元素相等的值,这样就可以把序列分为三部分:左子树(如果有).根结点和右子树(如果有). 2)将两个序列都分成三部分,这样就分别形成了根结点的左子树和右子树的先序遍历和后序遍历的序列. 3)重复1)和2)步骤,直至所有结点都处理完就可以完整构成一颗二叉树了. 根据分治法构造二叉树的代码实现: TreeNode *buildTree(vec

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

给出一二叉树的前序遍历的顺序和中序遍历的顺序我们可以由此得出后序遍历的顺序,根据它们的访问顺序,前序遍历的第一个结点肯定是根结点,与之对应在中序遍历找到对应的根结点的位置,那么在中序遍历中,根结点的左边的元素都属于左子树的元素,根结点右边的元素都属于右子树的元素,之后把左子树当成一个继续操作,就这样可以推出整个树,继而求出后序遍历: #include<iostream> #include<cstdlib> #include<cstring> #include<cs

输入层次遍历,输出中序,前序,后序遍历

题目描述 输入完全二叉树的层次遍历序列,输出该完全二叉树的中序遍历序列. 例如下面二叉树的层次遍历序列为“ABCDE",中序遍历为"DBEAC". A /    \ B      C /    \ D     E 遍历数采用递归写法,无需多说:而且前,中,后,皆为一法: 重要的是看怎么建立一个二叉树,且听分解: //输入层次遍历输出中序 #include <cstdio>#include <cstdlib>#include <cstring>

Binary Tree Inorder/Preorder Traversal 返回中序和前序/遍历二叉树的元素集合

给定一个二叉树,以集合方式返回其中序/先序方式遍历的所有元素. 有两种方法,一种是经典的中序/先序方式的经典递归方式,另一种可以结合栈来实现非递归 Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tree {1,#,2,3}, 1 2 / 3 return [1,3,2]. OJ's Binary Tree Serialization: The ser

二叉树的遍历,递归,迭代,层序,中序,前序,后序

#include<stdio.h> #include<stdlib.h> #include<queue> #include<stack> #include<iostream> using namespace std; struct node{ int key; node *left, *right; }; void insertTree(node* &root,int val) { node* tmp = (node*)malloc(si

根据中序和前序遍历还原二叉树

思路就是从前序遍历出发,到中序遍历中找到相应的根节点,然后确定左子树和右子树的范围 struct BiNode { int value; BiNode *leftchild; BiNode *rightchild; }; class solution { public: BiNode* BiTree(int *preorder,int *midorder,int length) { if(length < 0 || preorder == nullptr || midorder == nullp

[Swift]LeetCode105. 从前序与中序遍历序列构造二叉树 | Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that duplicates do not exist in the tree. For example, given preorder = [3,9,20,15,7] inorder = [9,3,15,20,7] Return the following binary tree: 3 / 9 20 /

前序和中序构造二叉树

题目链接: 涉及知识:二叉树的遍历 分析: 二叉树的前序遍历:根节点 -> 左子树 -> 右子树 二叉树的中序遍历:左子树 -> 根节点 -> 右子树 由此可知:前序遍历中访问到的第一个元素便是根节点,通过该点便可以将中序遍历分成左右两部分,左部分的元素用来生成该二叉树的左子树,右部分用来生成二叉树的右子树. 同样,左右两部分的元素中,首先在前序遍历中出现的便是该子树的根节点,很明显符合递归的定义. 代码如下: /* * @lc app=leetcode.cn id=105 lan

已知前序(后序)遍历序列和中序遍历序列构建二叉树(Leetcode相关题目)

1.文字描述: 已知一颗二叉树的前序(后序)遍历序列和中序遍历序列,如何构建这棵二叉树? 以前序为例子: 前序遍历序列:ABCDEF 中序遍历序列:CBDAEF 前序遍历先访问根节点,因此前序遍历序列的第一个字母肯定就是根节点,即A是根节点:然后,由于中序遍历先访问左子树,再访问根节点,最后访问右子树,所以我们找到中序遍历中A的位置,然后A左边的字母就是左子树了,也就是CBD是根节点的左子树:同样的,得到EF为根节点的右子树. 将前序遍历序列分成BCD和EF,分别对左子树和右子树应用同样的方法,