校招編程題(四) 二叉樹之根據前序和中序遍歷求按照深度優先遍歷打印的序列

摘要

根據前序遍歷和中序遍歷求該二叉樹按層遍歷的序列。


import java.util.Arrays;
import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeMap;

/************************************
 *                                  *
 *  @Modification  優化程序                        *
 *                                  *
 *  @version       1.0.1            *
 *                                  *
 *  @author        何明勝                            *
 *                                  *
 *  @Date   2017-04-02   12:38:04   *
 *                                  *
 ************************************/

public class FormerAndInTraToTree {
    int former_traversal[];//前序遍歷數組
    int former_cursor = 0;//前序遍歷數組遊標
    int in_traversal[];//中序遍歷數組

    int []result;//結果存儲數組
    TreeMap<Integer, Integer> tree_map = new TreeMap<Integer, Integer>();//結果在樹中的下標

    //初始化函數
    public void init(){
        @SuppressWarnings("resource")
        Scanner scanner = new Scanner(System.in);

        int len = scanner.nextInt();//樹中元素的個數

        //初始化
        former_traversal = new int[len];
        in_traversal = new int[len];
        result = new int[len];

        //讀入前序遍歷
        for(int i=0;i<len;i++){
            former_traversal[i] = scanner.nextInt();
        }
        //讀入中序遍歷
        for(int j=0;j<len;j++){
            in_traversal[j] = scanner.nextInt();
        }
    }

    //開始執行函數
    public void start() {   
        /*遞歸調用入口
        //第一個參數爲當前根節點的下標,初始化爲樹的根節點1
        //第二個參數爲當前根節點在中序遍歷中的位置下標
        //第三個參數爲當前中序數組
        //前序遍歷順序:根節點->左子節點->右子節點     中序遍歷:左子節點->根節點->右子節點     
        //前序遍歷是對根節點的遍歷,根據前序遍歷遊標former_cursor的值遍歷前序遍歷數組former_traversal的所有根節點
        //確定每個根節點在中序遍歷數組中的位置,//賦值給結果數組,下標爲當前root//
        //在該數組中其元素左邊的元素爲其左字樹,右邊爲其右子樹
        //對其子樹繼續遞歸,//左子樹根節點下標爲當前root*2,右子樹根節點下標爲當前root*2+1//
        //直到其左邊或者右邊只有一個元素時,則爲其左子節點和右子節點
        //賦值給結果數組,//左子節點下標爲當前root*2,右子節點下標爲root*2+1//
        */      
        myRecursive(1,inThisChild(in_traversal), in_traversal);

        //打印最終結果。tree自動排序,跟key中存儲的下標值,按序打印結果
        for(Iterator<Integer> iterator = tree_map.keySet().iterator();iterator.hasNext();){
            int tree_num = tree_map.get(iterator.next());
            System.out.print(result[tree_num]+ " ");
        }
    }

    //遞歸調用函數
    public void myRecursive(int root, int root_in_tra, int in_tra[]){
        //賦值當前根節點
        tree_map.put(root, former_cursor);//當前節點對應的下標爲key,當前節點在數組中的下標爲value
        result[former_cursor++] = in_tra[root_in_tra];//當前節點賦值給結果數組
        //中序遍歷當前節點已賦值,前序中游標former_cursor加1

        if(1 == root_in_tra){//當前根節點爲1,左邊只有一個元素,爲其左子節點
            tree_map.put(root*2, former_cursor);//保存當前根節點的下標
            result[former_cursor++] = in_tra[0];//賦值給當前根節點左子節點
            //中序遍歷當前節點已賦值,前序中游標former_cursor加1
        }
        else if(0 != root_in_tra){//排除當前根節點在數組最左邊的情況
            //截取當前根節點左邊的元素(左子樹)爲新數組
            int left_child[] = Arrays.copyOfRange(in_tra, 0, root_in_tra);

            //判斷當前根節點是否在左子樹中
            if(inThisChild(left_child) > -1){
                myRecursive(root*2, inThisChild(left_child), left_child);
            }
        }

        if(1 == (in_tra.length-1 -root_in_tra)){//當前根節點右邊只有一個元素,爲其右子節點
            tree_map.put(root*2+1, former_cursor);
            result[former_cursor++] = in_tra[root_in_tra+1];//賦值給右子節點
            //中序遍歷當前節點已賦值,前序中游標former_cursor加1
        }
        else if(0 != (in_tra.length-1 -root_in_tra)){//排除當前根節點在數組最右邊的情況
            //截取當前根節點右邊的元素(右子樹)爲新數組
            int right_child[] = Arrays.copyOfRange(in_tra, root_in_tra+1, in_tra.length);

            //判斷當前根節點是否在右子樹中
            if(inThisChild(right_child) > -1){
                myRecursive(root*2+1, inThisChild(right_child), right_child);
            }
        }
    }

    //判斷當前遊標對應的根節點是否在傳入的子樹中
    public int inThisChild(int []array){
        for(int i=0;i<array.length;i++){
            if(array[i] == former_traversal[former_cursor])
                return i;//若在,返回其在該子樹(數組)中的下標
        }
        return -1;//若不在,返回-1
    }

    public static void main(String[] args) {
        FormerAndInTraToTree test = new FormerAndInTraToTree();//實例化
        test.init();//初始化
        test.start();//開始執行
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章