二叉树遍历问题
一、DFS深度优先遍历
诀窍:先扎到尽头,再处理数值。整个root的问题,细化到最小子树来解决。
1.1 DFS三种顺序的递归遍历
1.1.1 前序遍历:中->左->右
function DFS(root){
let res = []
function DFS_first(root){
if(!root) return //递归的终止条件
res.push(root.val) //每层递归的处理语句,先存储当前的值
DFS_first(root.left) //后挖掘左节点,一直挖到底
DFS_first(root.right) //左节点触底后,开始挖掘右节点
}
}
1.1.2 中序遍历:左->中->右
function DFS(root){
let res = []
function DFS_in(root){
if(!root) return //递归的终止条件
DFS_first(root.left) //先挖掘左节点,一直挖到底
res.push(root.val) //到底之后,存储当前的值
DFS_first(root.right) //继续挖掘右节点
}
}
1.1.3 后序遍历:左->右->中
function DFS(root){
let res = []
function DFS_in(root){
if(!root) return //递归的终止条件
DFS_first(root.left) //先挖掘左节点,一直挖到底
DFS_first(root.right) //继续挖掘右节点
res.push(root.val) //到底之后,存储当前的值
}
}
1.2 DFS三种顺序的迭代遍历
1.2.1 前序遍历:中->左->右 入栈就要先右后左
function DFS_first(root){
let res = []
let stack = []
stack.push(root)
while(stack.length){
let node = stack.pop()
res.push(node.val)
node.right && stack.push(node.right)
node.left && stack.push(node.left)
}
return res
}
1.2.2 中序遍历:左->中->右(根节点没有立刻处理,需要指针)
function DFS_in(root){
let res = []
let stack = []
let cur = root
while(stack.length || cur){
if(cur){ //先把左边缘的节点push到stack
stack.push(cur)
cur = cur.left
}else{ //cur指向最底部的左节点的空左子节点,cur = null
let node = stack.pop()
res.push(node.val)
cur = node.right //cur指向最底部的左节点的空右子节点,cur = null
}
}
return res
}
1.2.3 后序遍历:左->右->中(将前序遍历左右掉转再整体翻转)
function DFS_back(root){
let res = []
let stack = []
while(stack.length){
let node = stack.pop()
res.push(node.val)
node.left && stack.push(node.left)
node.right && stack.push(node.right)
}
return res.reverse()
}
二、BFS广度优先遍历(维护一个stack)
逐层遍历,先水平探索,后深入发展。 ps:跟DFS的前序递归遍历很像,多了for循环,并且使用了shift。
function BFS(root){
let stack = [root]
let res = []
while(stack.length){
let len = stack.length
for(let i = 0;i<len;i++){ //借助for水平遍历
let node = stack.shift()
res.push(node.val)
node.left && stack.push(node.left)
node.right && stack.push(node.right)
}
}
return res
}
三、小结
此时,我们已经学习了二叉树遍历的7种方法:
- 6种DFS深度优先遍历方法,包括3种顺序(前序、中序、后序)*2种方法(递归和迭代)。
- 1种BFS广度优先遍历方法(迭代)。
其中,DFS三种递归方法结构相同,关键语句顺序不同,可以立马举一反三。DFS三种迭代方法,前序与后序相似,后序是前序的左右翻转再整体reverse,中序迭代则是较为复杂。BFS与DFS的前序迭代遍历十分相似,但是增加了for循环进行同层遍历,并且推荐使用shift。