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


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

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

  • 相关阅读:
    单行道
    学习C++50条忠告
    ROI
    OpenCV(图像处理)—访问像素的三种方法
    毕业课题项目——基于单目摄像头的距离测量
    API
    MFC
    STL
    debug、release
    Android中退出程序的提示框
  • 原文地址:https://www.cnblogs.com/AmoryWang-JavaSunny/p/7259423.html
Copyright © 2020-2023  润新知