题目:
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.youkuaiyun.com/hackbuteer1/article/details/6583988
[2] http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html