樹的遍歷-已知中序+(前序|後序)求層次遍歷
阿新 • • 發佈:2018-12-24
先來看一道題目:
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);
}
}
}
這樣我們便完成了已知後序,中序遍歷,求層次遍歷的結果。同理,我們對已知前序,中序,求後序遍歷的程式碼稍作修改,便可以求出已知前序,中序遍歷,求層次遍歷的結果
這裡便不再累述。