代码随想录 | Day14 | 2023.12.26 | 二叉树01

今日题目:

  1. 二叉树的递归遍历
  2. 二叉树的迭代遍历
  3. 二叉树的统一遍历(可选)

今日总结

没啥好说的,要能把迭代遍历给背下来。使用栈,前序和后序是一样的,只需要做个反转。中序需要单独使用指针来记录需要处理的节点。

三种遍历方法

要点

1.栈空即终止

代码:

func preorderTraversal(root *TreeNode) []int {
     if root == nil {
         return nil
     }
     stack := []*TreeNode{root}
     res := []int{}
     for len(stack) > 0 {
         node := stack[len(stack)-1]
         res = append(res, node.Val)
         stack = stack[:len(stack)-1]
         if node.Right != nil {
             stack = append(stack, node.Right)
         }
         if node.Left != nil {
             stack = append(stack, node.Left)
         }
     }
     return res
}

要点:

  1. 多了个reverse步骤
func postorderTraversal(root *TreeNode) []int {
    if root == nil {
        return nil
    }

    stack := []*TreeNode{}
    res := []int{}
    stack = append(stack, root)
    for len(stack) > 0 {
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        res = append(res, node.Val)
        if node.Left != nil {
            stack = append(stack, node.Left)
        }
        if node.Right != nil {
            stack = append(stack, node.Right)
        }
    }
    reverse(res)
    return res  
}

func reverse(nums []int) {
   for i := 0 ;i < len(nums)/2; i++{
       nums[i], nums[len(nums)-i-1] = nums[len(nums)-i-1], nums[i]
   }
   return
}

要点:

  1. 只有中序遍历时,出入栈的节点和当前要处理的节点不一定一致,所以需要单独的指针。
  2. 循环终止条件包括了cur != nil,因为可能栈空了,但是还需要处理,比如根节点处理完左子树,切换到右子树时栈会为空
func inorderTraversal(root *TreeNode) []int {
    if root == nil {
        return nil
    }
    stack := []*TreeNode{}
    res := []int{}
    var cur *TreeNode = root
    for cur != nil || len(stack) > 0 { //记住为啥判断条件是这两个
        if cur != nil {
            stack = append(stack, cur)
            cur = cur.Left
        } else {
            cur = stack[len(stack)-1]
            res = append(res, cur.Val)
            stack = stack[:len(stack)-1]
            cur = cur.Right  //类似于前序遍历,栈顶弹出后你还需要将弹出节点的右子树添加进栈
        }
    }
    return res
}

你可能感兴趣的:(算法)