題目:
Given a binary tree, return the inorder traversal
of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1
\
2
/
3
return [1,3,2]
.
思路:
借這個題來複習下樹的先序、中序、後序遍歷,遞歸以及非遞歸的實現。具體思路以及方法都在代碼註釋中寫明。
Binary_Tree_Inorder_Traversal.java 主要的算法類
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Binary_Tree_Inorder_Traversal {
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
boolean isFirst;//whether is the secondly visiting
TreeNode(int x) { val = x; }
}
//build tree
public TreeNode buildTree(int[] numbers) {
TreeNode[] nodes = new TreeNode[numbers.length];
for(int i = 0;i<nodes.length;i++) {
nodes[i] = new TreeNode(numbers[i]);
}
for(int i = 0;i<numbers.length;i++) {
if(2*i+1 < numbers.length) {
nodes[i].left = nodes[2*i+1];
}
if(2*i+2 < numbers.length) {
nodes[i].right = nodes[2*i+2];
}
}
return nodes[0];
}
/* * * * * * * * * * * * * * * * * * *
* 遞歸實現先序,中序,後序遍歷
* * * * * * * * * * * * * * * * * * */
//preorder
public void preorderRecursiveSub(List<Integer> result, TreeNode node) {
result.add(node.val);
if(node.left != null) preorderRecursiveSub(result, node.left);
if(node.right != null) preorderRecursiveSub(result, node.right);
}
public List<Integer> preorderRecursive(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
preorderRecursiveSub(result, root);
return result;
}
//inorder
public void inorderRecursiveSub(List<Integer> result, TreeNode node) {
if(node.left != null) inorderRecursiveSub(result, node.left);
result.add(node.val);
if(node.right != null) inorderRecursiveSub(result, node.right);
}
public List<Integer> inorderRecursive(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
inorderRecursiveSub(result, root);
return result;
}
//postorder
public void postorderRecursiveSub(List<Integer> result, TreeNode node) {
if(node.left != null) postorderRecursiveSub(result, node.left);
if(node.right != null) postorderRecursiveSub(result, node.right);
result.add(node.val);
}
public List<Integer> postorderRecursive(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
postorderRecursiveSub(result, root);
return result;
}
/* * * * * * * * * * * * * * * * * * * *
* 非遞歸實現先序,中序,後序遍歷
* * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * *
* 先序遍歷思路:先讓根進棧,只要棧不爲空,就可以做彈出操作,
* 每次彈出一個結點,記得把它的左右結點都進棧,記得右子樹先進棧,
* 這樣可以保證右子樹在棧中總處於左子樹的下面。 (preorderTraversal1)
* 或者
* 按照根節點->左孩子->右孩子的順序深度遍歷樹,在這個過程中,
* 輸出根節點的順序就決定了是否是先序或者中序遍歷。
* 當在深度搜索左孩子的時候,同時輸出該節點,則爲先序遍歷;(preorderTraversal2)
* 當完成深度搜索左孩子之後,再輸出該節點,則爲中序遍歷;(inorderTraversal)
*
* * * * * * * * * * * * * * * * * * */
public List<Integer> preorderTraversal1(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode current = root;
if(root == null) {
return result;
}
stack.push(root);
while(!stack.empty()) {
current = stack.pop();
result.add(current.val);
if(current.right != null) {
stack.push(current.right);
}
if(current.left != null) {
stack.push(current.left);
}
}
return result;
}
public List<Integer> preorderTraversal2(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode current = root;
if(root == null) {
return result;
}
while(current != null || !stack.empty()) {
while(current != null) {
result.add(current.val);//add
stack.push(current);
current = current.left;
}
if(!stack.empty()) {
current = stack.pop();
current = current.right;
}
}
return result;
}
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode current = root;
if(root == null) {
return result;
}
while(!stack.empty() || current != null) {
while(current != null) {
stack.push(current);
current = current.left;
}
if(!stack.empty()) {
current = stack.pop();
result.add(current.val);//add
current = current.right;
}
}
return result;
}
/* * * * * * * * * * * * * * * * * * * *
* 後序遍歷思路:因爲後序遍歷需要先將左右孩子都遍歷,才能將自己輸出,
* 所以實際access根節點爲兩次,所以設置一個標誌位來判斷是否是第二次訪問。(postorderTraversal1)
* 或者
* 要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點P,先將其入棧。
* 如果P不存在左孩子和右孩子,則可以直接訪問它;
* 或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被訪問過了,則同樣可以直接訪問該結點。
* 若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,
* 左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。(postorderTraversal2)
*
* * * * * * * * * * * * * * * * * * */
public List<Integer> postorderTraversal1(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode current = root;
if(root == null) {
return result;
}
while(!stack.empty() || current != null) {
while(current != null) {
stack.push(current);
current.isFirst = true;
current = current.left;
}
if(!stack.empty()) {
current = stack.pop();
if(current.isFirst) {
current.isFirst = false;
stack.push(current);
current = current.right;
}else{
result.add(current.val);//add
current = null;
}
}
}
return result;
}
public List<Integer> postorderTraversal2(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode current = root;
TreeNode pre = root;
if(root == null) {
return result;
}
stack.push(root);
while(!stack.empty()) {
current = stack.peek();
if((current.left == null && current.right == null) ||
(pre != null && (pre == current.left || pre == current.right))) {
result.add(current.val);//add
stack.pop();
pre = current;
}else{
//ensure the sequence
if(current.right != null) {
stack.push(current.right);
}
if(current.left != null) {
stack.push(current.left);
}
}
}
return result;
}
}
MainClass.java主要的測試類。
import java.util.ArrayList;
import java.util.List;
public class MainClass {
public static void main(String[] args) {
Binary_Tree_Inorder_Traversal bt = new Binary_Tree_Inorder_Traversal();
int[] numbers = {1,2,3,4,5,6,7};
/******************************************/
System.out.println("preorder testing:");
System.out.println(" Recursive:");
System.out.print(" ");
List<Integer> result = bt.preorderRecursive(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
System.out.println(" Non-Recursive:");
System.out.print(" ");
result = bt.preorderTraversal1(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
System.out.print(" ");
result = bt.preorderTraversal1(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
/******************************************/
System.out.println("inorder testing:");
System.out.println(" Recursive:");
System.out.print(" ");
result = bt.inorderRecursive(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
System.out.println(" Non-Recursive:");
System.out.print(" ");
result = bt.inorderTraversal(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
/******************************************/
System.out.println("postorder testing:");
System.out.println(" Recursive:");
System.out.print(" ");
result = bt.postorderRecursive(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
System.out.println(" Non-Recursive:");
System.out.print(" ");
result = bt.postorderTraversal1(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
System.out.print(" ");
result = bt.postorderTraversal2(bt.buildTree(numbers));
for(int i = 0;i<result.size();i++) {
System.out.print(result.get(i)+" ");
}
System.out.println();
}
}
主要參考:
[1] http://blog.csdn.net/hackbuteer1/article/details/6583988
[2] http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html