1. 程式人生 > >樹的遍歷-已知中序+(前序|後序)求層次遍歷

樹的遍歷-已知中序+(前序|後序)求層次遍歷

先來看一道題目:

L2-2. 樹的遍歷

時間限制 400 ms
記憶體限制 65536 kB
程式碼長度限制 8000 B
判題程式 Standard 作者 陳越

給定一棵二叉樹的後序遍歷和中序遍歷,請你輸出其層序遍歷的序列。這裡假設鍵值都是互不相等的正整數。

輸入格式:

輸入第一行給出一個正整數N(<=30),是二叉樹中結點的個數。第二行給出其後序遍歷序列。第三行給出其中序遍歷序列。數字間以空格分隔。

輸出格式:

在一行中輸出該樹的層序遍歷的序列。數字間以1個空格分隔,行首尾不得有多餘空格。

輸入樣例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
輸出樣例:
4 1 6 3 5 7 2

首先我們先看一下已知前序,中序。求後序遍歷的結果。

package com.zjianhao.tree;


/**
 * Created by 張建浩(Clarence) on 2016-5-22 21:21.
 * the author's website:http://www.zjianhao.cn
 * the author's github: https://github.com/zhangjianhao
 */

public class Tree {

    private static int [] L = {4,1,8,3,2,6,5,7};
    private int [] V = {8,1,2,3,4,5,6,7};
    private static int [] R = {8,2,3,1,5,7,6,4};
    public static void main(String[] args) {
        Tree tree = new Tree();
        tree.solvePostOrder(0,0,L.length);
 
    }




    /**
     *已知前序遍歷,中序遍歷,求後序遍歷
     * @param preStart
     * @param inStart
     * @param length
     */
    public void solvePostOrder(int preStart,int inStart,int length){
        if (length<=0)
            return;
        int v = L[preStart];
        int len = getLength(inStart,length,v);//獲取左子樹的長度len,則右子樹的長度為length-len-1
        solvePostOrder(preStart+1,inStart,len);//遞迴解決左子樹
        solvePostOrder(preStart+len+1,inStart+len+1,length-len-1);//右子樹
        System.out.print(v+" ");//列印根節點

    }


    public int getLength(int start,int length,int v){//根據中間節點,求左子樹的長度
        for (int i = start,count = 0; count<length; i++,count++){
            if (V[i] == v)
                return count;
        }
        return 0;
    }

}

已知中序,後序遍歷,求前序遍歷結果。

此處post初始傳值為:後序的長度-1,即後序最後一個元素的索引。因為後序遍歷的順序為:左右中(LRV)所以根節點必然是最後一個,因此我們要從後往前尋找。

 public void solvePreOrder(int post,int inStart,int length){
        if (length<=0)
            return ;
        int v = R[post];
        System.out.print(v+" ");//
        int len = getLength(inStart,length,v);//left tree length
        solvePreOrder(post-(length-len),inStart,len);//solve left tree
        solvePreOrder(post-1,inStart+len+1,length-len-1);//solve right tree
    }

好了,由中序加任意遍歷次序我們全部都解決了。現在我們來看一下題目。

題目中要求層次遍歷。我們可以嘗試由後續和中序遍歷構造出一棵樹來,樹的層次遍歷就很容易了。

首先我們需要對上述已知後序中序遍歷的情況的程式碼稍作修改

首先定義一個節點類:

 private class Node<E>{
         E data;
         Node left;
         Node right;
    }
 public Node<Integer> solvePreOrder(int post,int inStart,int length){
        if (length<=0)
            return null;
        int v = R[post];
        Node<Integer> root = new Node<>();
        root.data = v;
        int len = getLength(inStart,length,v);//left tree length
        root.left = solvePreOrder(post-(length-len),inStart,len);//solve left tree,記錄根節點的左子樹
        root.right = solvePreOrder(post-1,inStart+len+1,length-len-1);//solve right tree <span style="font-family: Arial, Helvetica, sans-serif;">記錄根節點的右子樹</span>

        return root;
    }
構造完樹後,我們按照層次遍歷的結果對樹進行遍歷,樹的層次遍歷程式碼我們應該都很熟悉了:
public void solveLevelOrder(int post,int inStart,int length){
        //
        Node<Integer> root = solvePreOrder(post,inStart,length);
        Queue<Node> queue = new LinkedList<>();
        System.out.println(root.left.data+":"+root.right.data);
        queue.add(root);
        while (!queue.isEmpty()){
            Node<Integer> rt = queue.poll();
            System.out.print(rt.data+" ");
            if (rt.left != null){
                queue.add(rt.left);
            }
            if (rt.right != null){
                queue.add(rt.right);
            }
        }
    }
這樣我們便完成了已知後序,中序遍歷,求層次遍歷的結果。同理,我們對已知前序,中序,求後序遍歷的程式碼稍作修改,便可以求出已知前序,中序遍歷,求層次遍歷的結果

這裡便不再累述。