后序遍历
概念
「后序遍历」指先遍历节点的左子树,再遍历节点的右子树,最后访问节点,按照这种规则不重复地访问树中所有节点的过程。
思路
树的结构如下,以变量root
保存
// 节点的数据结构
function Node(value) {
this.value = value
this.left = null
this.right = null
}
root {
value: 'A',
left: {
value: 'B',
left: {
value: 'D',
left: {
value: 'H',
left: null,
right: {
value: 'K',
left: null,
right: null
}
},
right: null
},
right: {
value: 'E',
left: null,
right: null
}
},
right: {
value: 'C',
left: {
value: 'F',
left: {
value: 'I',
left: null,
right: null
},
right: null
},
right: {
value: 'G',
left: null,
right: {
value: 'J',
left: null,
right: null
}
}
}
}
先遍历节点的左子树,再遍历节点的右子树,最后访问节点。其中一个节点会被使用三次,第一次被用于遍历其左子树,第二次被用于遍历其右子树,第三次被用于访问节点。第一次在到达该节点时被使用,第二次在左子树遍历结束后被使用,第三次在右子树遍历结束后使用。第一次到达该节点可以直接使用该节点,与此同时,需要将节点存入栈中,方便第二次、第三次使用。
代码
const postOrderTraverse = root => {
let current = root,
stack = []
while (current || stack.length !== 0) {
if (current) {
stack.push(current) // 存入栈中用于从节点去遍历其右子树
stack.push(current) // 存入栈中用于访问节点值
current = current.left // 遍历左子树
} else {
current = stack.pop()
if (current === stack[stack.length - 1]) { // 若栈顶节点和紧随的节点一样,说明是第二次使用该节点
current = current ? current.right : null // 从节点去遍历其右子树
} else { // 若栈顶节点和紧随的节点一样,说明是第三次使用该节点
console.log(current.value) // 访问节点值
current = null // 使下一次循环进入current不存在的代码片段中,好处理栈顶节点
// current = stack.pop() 若写成这样,会进入current存在的代码片段,栈顶节点会再次重复入栈
}
}
}
}
postOrderTraverse(binaryTree.root)
// K H D E B I F J G C A
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。