树的遍历
LeetCode上的三道关于树的遍历题目:
- 144二叉树的前序遍历
- 94二叉树的中序遍历
- 145二叉树的后序遍历
递归解法
递归是最容易的。递归是函数自身调用自身,涉及到保护现场(变量入栈,记录地址等),时间和空间开销较大,而这操作都是在栈上,调用层级太多很容易溢出。 其与迭代最大的区别就是是否会栈溢出。
前序遍历
public void dfs(TreeNode root) {
if(root == null) {
return;
}
visit(root);
dfs(root.left);
dfs(root.right);
}
中序遍历
public void dfs(TreeNode root) {
if(root == null) {
return;
}
dfs(root.left);
visit(root);
dfs(root.right);
}
后序遍历
public void dfs(TreeNode root) {
if(root == null) {
return;
}
dfs(root.left);
dfs(root.right);
visit(root);
}
非递归解法
非递归的方法是用存储代替计算,就是在建立树时,实现了存储展开,相当于存储了未来需要遍历的路径,速度更快。
前序遍历
public void dfs(TreeNode root) {
if(root == null) return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
visit(node);
if(node.right != null) stack.push(node.right);
if(node.left != null) stack.push(node.left);
}
}
中序遍历
public void dfs(TreeNode root) {
if(root == null) return;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()) {
while(cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode node = stack.pop();
visit(node);
cur = node.right;
}
}
后序遍历
用两个栈
public void dfs(TreeNode root) {
if(root == null) return;
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
s1.push(root);
while(!s1.isEmpty()) {
TreeNode node = s1.pop();
s2.push(node);
if(peek.left != null) s1.push(peek.left);
if(peek.right != null)
s1.push(peek.right);
}
while(!s2.isEmpty()) {
TreeNode node = s2.pop();
visit(node);
}
}
用一个栈
public void dfs(TreeNode root) {
if(root == null) return;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = null;
stack.push(root);
while(!stack.isEmpty()) {
TreeNode peek = stack.peek();
if(peek.left != null && peek.left != cur && (peek.right != cur || cur == null)) {
stack.push(peek.left);
} else if(peek.right != null && peek.right != cur) {
stack.push(peek.right);
} else {
visit(stack.pop());
cur = peek;
}
}
}