操作
一、前序遍历
1.1 递归
思路: 定义 preorder(root)
表示当前遍历到 root
节点的答案。按照定义,我们只要首先将 root
节点的值加入答案,然后递归调用 preorder(root.left)
来遍历 root
节点的左子树,最后递归调用 preorder(root.right)
来遍历 root
节点的右子树即可,递归终止的条件为碰到空节点。
实现
function preorderTraversal(root) {
const result = [];
const preorder = (root) => {
if (root == null) {
return;
}
result.push(root.val);
preorder(root.left);
preorder(root.right);
};
preorder(root);
return result;
}
1.2 迭代
思路: 区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来
实现
function preorderTraversal(root) {
if (root == null) {
return [];
}
const result = [];
const stack = [];
let current = root;
while (stack.length !== 0 || current != null) {
while (current != null) {
result.push(current.val);
stack.push(current);
current = current.left;
}
current = stack.pop();
current = current.right;
}
return result;
}
二、中序遍历
2.1 递归
思路 定义 inorder(root)
表示当前遍历到 root
节点的答案,那么按照定义,我们只要递归调用 inorder(root.left)
来遍历 root
节点的左子树,然后将 root
节点的值加入答案,再递归调用inorder(root.right)
来遍历 root
节点的右子树即可,递归终止的条件为碰到空节点。
实现
function inorderTraversal(root) {
const result = [];
const inorder = (root) => {
if (!root) {
return;
}
inorder(root.left);
result.push(root.val);
inorder(root.right);
};
inorder(root);
return result;
}
2.2 迭代
思路: 方法一的递归函数我们也可以用迭代的方式实现,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其他都相同
实现
function inorderTraversal(root) {
const result = [];
const stack = [];
let current = root;
while (current != null || stack.length !== 0) {
while (current != null) {
stack.push(current);
current = current.left;
}
current = stack.pop();
result.push(current.val);
current = current.right;
}
return result;
}
三、后序遍历
3.1 递归
思路: 定义 postorder(root)
表示当前遍历到 root
节点的答案。按照定义,我们只要递归调用 postorder(root->left)
来遍历 root
节点的左子树,然后递归调用 postorder(root->right)
来遍历 root
节点的右子树,最后将 root
节点的值加入答案即可,递归终止的条件为碰到空节点。
实现
function postorderTraversal(root){
const result = [];
const postorder = (root)=>{
if(root == null){
return
}
postorder(root.left);
postorder(root.right);
result.push(root.val);
}
postorder(root);
return result;
}