参考大神的神作:http://blog.csdn.net/fightforyourdream/article/details/16843303
对于后序遍历,我们理解为将右节点为先的先序遍历翻转,会思考上简单很多,就是用右节点为先的先序遍历做,再用第二个栈进行翻转,就是后序遍历。
/*
* 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec
* (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2)
* */
public static void preorderTraversalRec(TreeNode root) {
if (root == null) {
return;
}
System.out.print(root.val + " ");
preorderTraversalRec(root.left);
preorderTraversalRec(root.right);
}
/*
* 前序遍历,Iteration 算法. 把根节点存在stack中。
* */
public static void preorderTraversal(TreeNode root) {
if (root == null) {
return;
}
Stack
s = new Stack
();
s.push(root);
while (!s.isEmpty()) {
TreeNode node = s.pop();
System.out.print(node.val + " ");
if (node.right != null) { //
s.push(node.right);
}
// 我们需要先压入右节点,再压入左节点,这样就可以先弹出左节点。
if (node.left != null) {
s.push(node.left);
}
}
}
/*
* 中序遍历
* */
public static void inorderTraversalRec(TreeNode root) {
if (root == null) {
return;
}
inorderTraversalRec(root.left);
System.out.print(root.val + " ");
inorderTraversalRec(root.right);
}
/**
* 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内,
* 然后输出栈顶元素,再处理栈顶元素的右子树
* http://www.youtube.com/watch?v=50v1sJkjxoc
*
* 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上
* http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
*/
public static void inorderTraversal(TreeNode root) {
if (root == null) {
return;
}
Stack
s = new Stack
();
TreeNode cur = root;
while(true) {
// 把当前节点的左节点都push到栈中.
while (cur != null) {
s.push(cur);
cur = cur.left;
}
if (s.isEmpty()) {
break;
}
// 因为此时已经没有左孩子了,所以输出栈顶元素
cur = s.pop();
System.out.print(cur.val + " ");
// 准备处理右子树
cur = cur.right;
}
}
// 后序遍历
/*
* 1
/ \
2 3
/ \ \
4 5 6
if put into the stack directly, then it should be:
1, 2, 4, 5, 3, 6 in the stack.
when pop, it should be: 6, 3, 5, 4, 2, 1
if I
* */
public static void postorderTraversalRec(TreeNode root) {
if (root == null) {
return;
}
postorderTraversalRec(root.left);
postorderTraversalRec(root.right);
System.out.print(root.val + " ");
}
/**
* 后序遍历迭代解法
* http://www.youtube.com/watch?v=hv-mJUs5mvU
* http://blog.csdn.net/tang_jin2015/article/details/8545457
* 从左到右的后序 与从右到左的前序的逆序是一样的,所以就简单喽! 哈哈
* 用另外一个栈进行翻转即可喽
*/
public static void postorderTraversal(TreeNode root) {
if (root == null) {
return;
}
Stack
s = new Stack
(); Stack
out = new Stack
(); s.push(root); while(!s.isEmpty()) { TreeNode cur = s.pop(); out.push(cur); if (cur.left != null) { s.push(cur.left); } if (cur.right != null) { s.push(cur.right); } } while(!out.isEmpty()) { System.out.print(out.pop().val + " "); } } /* * 分层遍历二叉树(按层次从上往下,从左往右)迭代 * 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点 * ,访问,若左子节点或右子节点不为空,将其压入队列 * */ public static void levelTraversal(TreeNode root) { if (root == null) { return; } Queue
q = new LinkedList
(); q.offer(root); while (!q.isEmpty()) { TreeNode cur = q.poll(); System.out.print(cur.val + " "); if (cur.left != null) { q.offer(cur.left); } if (cur.right != null) { q.offer(cur.right); } } } public static void levelTraversalRec(TreeNode root) { ArrayList
> ret = new ArrayList
>(); levelTraversalVisit(root, 0, ret); System.out.println(ret); } /** * 分层遍历二叉树(递归) * 很少有人会用递归去做level traversal * 基本思想是用一个大的ArrayList,里面包含了每一层的ArrayList。 * 大的ArrayList的size和level有关系 * * http://discuss.leetcode.com/questions/49/binary-tree-level-order-traversal#answer-container-2543 */ public static void levelTraversalVisit(TreeNode root, int level, ArrayList
> ret) { if (root == null) { return; } // 如果ArrayList的层数不够用, 则新添加一层 // when size = 3, level: 0, 1, 2 if (level >= ret.size()) { ret.add(new ArrayList
()); } // visit 当前节点 ret.get(level).add(root.val); // 将左子树, 右子树添加到对应的层。 levelTraversalVisit(root.left, level + 1, ret); levelTraversalVisit(root.right, level + 1, ret); }