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


/**
 * 重建二叉树 ;根据给定的前序和中序遍历的结果,构造出树的结构
 */
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);
    }

}

 

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

posted @ 2017-07-30 16:04  AmoryWang_JavaSunny  阅读(779)  评论(0编辑  收藏  举报