刷题---树篇---145. 二叉树的后序遍历

99 篇文章 0 订阅
30 篇文章 1 订阅

给定一个二叉树,返回它的 后序 遍历。

示例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

刷题---树篇---94. 二叉树的中序遍历

刷题---树篇---144. 二叉树的前序遍历

后序遍历的非递归版本难度更大,但其实大体的思路框架与其他两种差不多,难在对于栈顶元素的右子节点的处理上。

在后序遍历中遵循的规则是:左-右-中。

那么对左子树的处理和中序遍历一样,可以使用:

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
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值