前中后序遍历的递归方式。
其实,前中后序的遍历,走的路径是一样的,只是访问结点的时间不同而已。
非递归进行前中后序遍历(使用栈)
题目描述:
List preorderTraversal(TreeNode root)
List inorderTraversal(TreeNode root)
List postorderTraversal(TreeNode root)
题目链接:
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
1.前序遍历
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
//迭代解决 使用栈
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode tmp = root;
while (!stack.isEmpty() || tmp != null) {
while (tmp != null) {
//前序遍历 第一次路过就访问
list.add(tmp.val);
stack.push(tmp);
tmp = tmp.left;
}
tmp = stack.pop();
tmp = tmp.right;
}
return list;
}
2.中序遍历
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new LinkedList<>();
//迭代解决 使用栈
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode tmp = root;
while (!stack.isEmpty() || tmp != null) {
while (tmp != null) {
stack.push(tmp);
tmp = tmp.left;
}
tmp = stack.pop();
//中序遍历 第二次路过就访问
list.add(tmp.val);
tmp = tmp.right;
}
return list;
}
3.后序遍历
后序遍历和前序遍历、中序遍历不太一样。之前使用栈时,前序遍历是在元素入栈时就访问,中序遍历是在元素出栈时再访问。一个元素就入栈、出栈共两次访问,没有再第三次路过,因此后序遍历不容易直接写出来。
但是我们观察到:
后序遍历: 左 右 根 的顺序, 如果我们把它顺序反过来呢? 就是 根 右 左 ,可以认为这是一种特殊的“前序遍历”。我们可以按照前序遍历的思路,很容易的写出 根 右 左 的顺序,然后把结果反过来不就可以了吗!
public List<Integer> postorderTraversal(TreeNode root){
//后序遍历
//左右根 反过来的顺序就是 根右左,根右左是一种特殊的"前序遍历",这样遍历出来之后,只需要把它反过来就行了。
LinkedList<Integer> result = new LinkedList<>();
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode tmp = root;
while (tmp != null || !stack.isEmpty()) {
while (tmp != null) {
stack.push(tmp);
//插到第一个,相当于就是进行了逆序
result.addFirst(tmp.val);
tmp = tmp.right;
}
tmp = stack.pop();
tmp = tmp.left;
}
return result;
}
还有一种思路:
/**
* 后序遍历
* 后序遍历是第三次遇到该结点时,才可以进行访问。
* 使用栈来实现。
* 要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。
* 当结点没有左右子节点时可以直接访问,或者上一个访问的子节点是自己的儿子结点,则可以访问该结点。并将该结点弹栈
* 否则就将该结点的右儿子和左儿子入栈。保证出栈时左儿子在前
* @param root
* @return
*/
public List<Integer> postorderTraversal(TreeNode root) {
//迭代实现
List<Integer> result = new LinkedList<>();
if (root == null) {
return result;
}
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode cur = null, pre = null;
stack.push(root);
while (!stack.isEmpty()) {
cur = stack.peek();
if (!hasChild(cur) || lastVisitedIsChild(cur, pre)) {
//访问
result.add(cur.val);
pre = stack.pop();
} else {
if (cur.right != null) {
stack.push(cur.right);
}
if (cur.left != null) {
stack.push(cur.left);
}
}
}
return result;
}
private boolean lastVisitedIsChild(TreeNode cur, TreeNode pre) {
return pre != null && (pre == cur.left || pre == cur.right);
}
private boolean hasChild(TreeNode t) {
return (t.left != null) || (t.right != null);
}
来源:CSDN
作者:bobo1356
链接:https://blog.csdn.net/bobo1356/article/details/103951500