[網鼎杯 2020 青龍組]jocker
阿新 • • 發佈:2020-08-09
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;
}
}
}