根據中序和前序序列來構造二叉樹,以寬度優先遍歷輸出

 
 
/**
 * 重建二叉樹 ;根據給定的前序和中序遍歷的結果,構造出樹的結構
 */
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);
    }

}

 

總結一下 : 這個遞歸的過程是逐漸優化的過程,容易搞混的地方主要在於對於前序序列和中序序列的中的參數變化,因此一點很重要,每一步的目的是什麼,須要哪些參數來知足需求,搞清楚了以後在寫代碼.java

相關文章
相關標籤/搜索