golang二叉树后序遍历

题面

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

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

输出: [3,2,1]

分析

定义 在二叉树中,先左后右再根,即首先遍历左子树,然后遍历右子树,最后访问根结点

  • 已知前序遍历和中序遍历,就能确定后序遍历

递归遍历

  1. 后序遍历左子树
  2. 后序遍历右子树
  3. 访问根结点
  4. 二叉树为空则结束返回
type TreeNode struct {
    Val int
   	Left *TreeNode
    Right *TreeNode
}

func postorderTraversal(root *TreeNode) []int {
   if root == nil {
       return []int{}
   }
   l :=[]int{}
   left := postorderTraversal(root.Left)
   right:=postorderTraversal(root.Right)
   if len(left)>0 {
       l = append(l,left...)
   }
   if len(right)>0 {
       l = append(l,right...)
   }
   l = append(l,root.Val)

   return l
}

非递归遍历

核心思想:用栈来保存先前走过的路径,以便可以在访问完子树后,可以利用栈中的信息,回退到当前节点的双亲节点,进行下一步操作

与递归区别

  • 在非递归算法中,利用栈回退到时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点
  • 如果从左子树回退到根节点,此时就应该去访问右子树,而如果从右子树回退到根节点,此时就应该访问根节点。
  • 相比前序和后序,必须得在压栈时添加信息,以便在退栈时可以知道是从左子树返回,还是从右子树返回进而决定下一步的操作

import "container/list"

type Element struct {
    Bt *TreeNode
    Direct bool
}

func postorderTraversal(root *TreeNode) []int {
  
   l :=[]int{}
   stack := list.New()
   e :=&Element{Bt:root}
   stack.PushBack(e)
    for stack.Len()>0 {
        top := stack.Back().Value.(*Element)
        // 不可直接访问
        if !top.Direct {
            rt:= top.Bt
            stack.Remove(stack.Back())
            // 入栈顺序与后序遍历相反,确保出栈顺序为左->右->根
            if rt != nil {
                // 根节点
                stack.PushBack(&Element{Bt:rt,Direct:true})
                // 右节点
                stack.PushBack(&Element{Bt:rt.Right})
                // 左节点
                stack.PushBack(&Element{Bt:rt.Left})
            }
        }
        // 为右节点, 可直接访问
        if top.Direct {
            l = append(l,top.Bt.Val)
            stack.Remove(stack.Back())
        }
    }

   return l
}

标志位分析

  • 栈的进进出出
  • 当左子树处理完毕出栈,返回根节点时,不能立即处理当前根节点
  • 给根节点打标志,表明左已处理完,此时需要根指向的右子树节点入栈
    本质栈进进出出,弹出的栈元素,需要对其相关节点的入栈进行可行性评估

python 巧妙版

  • 充分复用层序遍历特点
  • 栈的反序,结合上步自顶向下构建后序非递归遍历,无须使用标志位
  • 使用标志位的关键在于区分途经节点,访问节点,与节点出入栈,用标志表明是否已经来过,再次遇到意味着访问,即取值,彻底出栈
class Solution:
    def postorderTraversal(self , root ):
        st,rs = [],[]
        while root:
            rs.insert(0,root.val)
            root.left and st.append(root.left)
            root.right and st.append(root.right)
            root = st.pop() if st else None
        return rs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值