给定一个二叉树,返回它的 后序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
后序遍历的非递归版本难度更大,但其实大体的思路框架与其他两种差不多,难在对于栈顶元素的右子节点的处理上。
在后序遍历中遵循的规则是:左-右-中。
那么对左子树的处理和中序遍历一样,可以使用:
for k != nil {
stack = append(stack,k)
k = k.Left
}
例如:
1
2 3
这样的二叉树,经过上面操作后,栈中元素为:1,2.其中 2 时栈顶。
此时对 2 的处理很关键,如果是下面的树:
1
2 3
\
4
那么2还有一个右子节点,所以根据后序遍历 左-右-中,则此时4必然要入栈,再进行下一轮操作。
那么没有节点4的情况下,2可以直接出栈。
因为与前序和中序不同,后序遍历非递归在左边处理完之后会回到根节点,再对根节点的右边进行处理,然后再回到根节点并输出根节点。
前序遍历直接输出了根节点,中序遍历在处理完左边回到根后也直接输出了根。
t := stack[len(stack)-1]
if t.Right == nil {
stack = stack[:len(stack)-1]
res = append(res,t.Val)
} else {
k = t.Right
t.Right = nil
}
t.Right = nil 表示已经遍历过这个节点的右子节点,既可以看作是一个标志,防止在后面出栈操作时重复计算造成死循环。
完成代码:
go非递归:
func postorderTraversal(root *TreeNode) []int {
res := make([]int,0)
stack := make([]*TreeNode,0)
k := root
for len(stack) != 0 || k != nil {
for k != nil {
stack = append(stack,k)
k = k.Left
}
t := stack[len(stack)-1]
if t.Right == nil {
stack = stack[:len(stack)-1]
res = append(res,t.Val)
} else {
k = t.Right
t.Right = nil
}
}
return res
}