前言
遍历树的两个策略
DFS 分为 先序遍历 中序遍历 后序遍历
BFS 可以按照层次的顺序从上到下遍历所有的节点
构造一颗二叉树
const node = (value,left,right)=>{
return {
value,
left,
right
}
}
const binaryTree =
node("A",
node("B",node("D")),
node("C",
node("E",undefined,node("G")),
node("F",node("H"),node("J"))
)
)
/%E9%81%8D%E5%8E%86%E4%BA%8C%E5%8F%89%E6%A0%91.jpg)
1. DFS 先序遍历
利用递归先序遍历
let resultFirst = []
const traverseRootFirst = (bTree) => {
if(!bTree) { return}
resultFirst.push(bTree.value)
traverseRootFirst(bTree.left)
traverseRootFirst(bTree.right)
}
traverseRootFirst(binaryTree)
console.log('先序遍历')
console.log(resultFirst) // ["A", "B", "D", "C", "E", "G", "F", "H", "J"]
不利用递归先序遍历
自己维护一个栈 当前节点指向根节点
- 如果当前节点不为空 就将当前节点入栈 并push到结果数组中 并让当前节点指向该节点的左节点
- 如果当前节点为空 就从栈中pop一个节点 并让当前节点指向pop出节点的右节点
如果栈不为空 或者 当前节点不为空 重复以上步骤
let resultFirst2 = []
const traverseRootFirst2 = (bTree) => {
const stack = []
let current = bTree
while(stack.length || current){
if(current){
resultFirst2.push(current.value)
stack.push(current)
current = current.left
}else{
current = stack.pop()
current = current.right
}
}
}
traverseRootFirst2(binaryTree)
console.log('\n 不利用递归先序遍历')
console.log(resultFirst2) // ["A", "B", "D", "C", "E", "G", "F", "H", "J"]
2 DFS 中序遍历
递归
let resultMiddle = []
const traverseRootMiddle = (bTree) => {
if(!bTree) { return }
traverseRootMiddle(bTree.left)
resultMiddle.push(bTree.value)
traverseRootMiddle(bTree.right)
}
traverseRootMiddle(binaryTree)
console.log('中序遍历')
console.log(resultMiddle) // ["D", "B", "A", "E", "G", "C", "H", "F", "J"]
不利用递归
自己维护一个栈 当前节点指向根节点
- 如果当前节点不为空 就让当前节点指向该节点的左节点
- 如果当前节点为空 就从栈中pop一个节点 并将该节点push到结果数组中 并将当前节点指向该节点的右节点
如果栈不为空 或者 当前节点不为空 重复以上步骤
与先序遍历唯一不同的就是什么时候放入结果数组
let resultMiddle2 = []
const traverSeRootMiddle2 = (bTree) => {
const stack = []
let current = bTree
while(stack.length || current){
if(current){
stack.push(current)
current = current.left
}else{
current = stack.pop()
resultMiddle2.push(current.value)
current = current.right
}
}
}
traverSeRootMiddle2(binaryTree)
console.log('\n 不利用递归中序遍历')
console.log(resultMiddle2) // ["D", "B", "A", "E", "G", "C", "H", "F", "J"]
3 DFS 后续遍历
递归
let resultLast = []
const traverseRootLast = (bTree) => {
if(!bTree) { return }
traverseRootLast(bTree.left)
traverseRootLast(bTree.right)
resultLast.push(bTree.value)
}
traverseRootLast(binaryTree)
console.log('后序遍历')
console.log(resultLast) // ["D", "B", "G", "E", "H", "J", "F", "C", "A"]
4 BFS
维护一个队列 将根节点放入队列中
- 从队列中取出一个节点node
- 如果node节点为空的话 就将当前的左右节点先后放入队列中
- 如果当前节点为空 队列中push null
如果队列部位空 重复以上步骤 直到队列中的节点全部被取出 遍历完成
var serialize = (root) => {
let queue = [root]
let res = []
while(queue.length){
let node = queue.shift()
if(node){
res.push(node.val)
queue.push(node.left)
queue.push(node.right)
}else{
res.push('X')
}
}
return res
}