一、前言
- 此篇是关于二叉树的深度遍历,想看广度遍历的可以看我的这篇文章-用JavaScript搞定二叉树的层序遍历。
- 此篇将用递归和迭代法来遍历二叉树, 并且递归和迭代都是通用写法。迭代用的是标记法
二、遍历顺序说明
2.1 前序遍历顺序
2.2 中序遍历顺序
2.3后序遍历顺序
三、代码
- 递归没啥说的,有用到闭包。递归需要注意三个地方:递归单层逻辑、递归函数参数返回值、递归结束条件
- 迭代法:标记法,访问过的标记为true, 未访问过的标记为false;当栈弹出的是访问过的节点,输出到结果集;当栈弹出的是未访问过的节点,压栈(压栈顺序和前序遍历顺序相反),此次压栈注意要改变本身的状态,因为本身已经变成已访问节点了
- git代码链接
3.1 前序遍历代码
3.1.1 前序递归法
var preorderTraversal = function(root) {
const res = []
const preorder = function (node) {
if(node === null) return
res.push(node.val)
node.left && preorder(node.left)
node.right && preorder(node.right)
}
preorder(root)
return res
};
3.1.2 前序迭代法
- 标记法,访问过的标记为true, 未访问过的标记为false
- 当栈弹出的是访问过的节点,输出到结果集
- 当栈弹出的是未访问过的节点,右子树、左子树、本身进行依次压栈(压栈顺序和前序遍历顺序相反),此次压栈注意要改变本身的状态,因为本身已经变成已访问节点了
const preorderTraversal = function (root) {
const res = []
if(root === null) return res
const stack = [{
node: root, isSearched: false
}]
while (stack.length) {
const {node, isSearched} = stack.pop()
if(isSearched) {
res.push(node.val)
} else {
node.right && stack.push({node: node.right, isSearched: false})
node.left && stack.push({node: node.left, isSearched: false})
stack.push({node: node, isSearched: true})
}
}
return res
}
3.2 中序遍历代码
3.2.1 中序递归法
**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
const inorderTraversal = function(root) {
const res = []
const inorder = function(node) {
if(node === null) return
node.left && inorder(node.left)
res.push(node.val)
node.right && inorder(node.right)
}
inorder(root)
return res
};
3.2.2 中序迭代法
- 标记法,访问过的标记为true, 未访问过的标记为false
- 当栈弹出的是访问过的节点,输出到结果集
- 当栈弹出的是未访问过的节点,右子树、本身、左子树进行依次压栈(压栈顺序和中序遍历顺序相反),此次压栈注意要改变本身的状态,因为本身已经变成已访问节点了
const inorderTraversal = function(root) {
const res = []
if(root === null) return res
const stack = [{node: root, isSearched: false}]
while (stack.length) {
const {node, isSearched} = stack.pop()
if(isSearched) {
res.push(node.val)
} else {
node.right && stack.push({node: node.left, isSearched: false})
stack.push({node: node, isSearched: true})
node.length && stack.push({node: node.right, isSearched: false})
}
}
return res
};
3.3 后序遍历代码
3.3.1 后序递归法
const postorderTraversal = function(root) {
const res = []
const inorder = function(node) {
if(node === null) return
node.left && inorder(node.left)
node.right && inorder(node.right)
res.push(node.val)
}
inorder(root)
return res
}
3.3.2 后序迭代法
- 标记法,访问过的标记为true, 未访问过的标记为false
- 当栈弹出的是访问过的节点,输出到结果集
- 当栈弹出的是未访问过的节点,本身、右子树、左子树进行依次压栈(压栈顺序和后序遍历顺序相反),此次压栈注意要改变本身的状态,因为本身已经变成已访问节点了
const postorderTraversal = function(root) {
const res = []
if(root === null) return res
const stack = [{
node: root, isSearched: false
}]
while (stack.length) {
const {node, isSearched} = stack.pop()
if(isSearched) {
res.push(node.val)
} else {
stack.push({node: node, isSearched: true})
node.right && stack.push({node: node.right, isSearched: false})
node.left && stack.push({node: node.left, isSearched: false})
}
}
return res
}