二叉树遍历

二叉树顾名思义就是最多有二个叉,即最多两个子节点,且不要求节点之间的大小关系。

二叉树的遍历方式按照“左右根”的顺序不同分为以下几种:

  1. 前序遍历:根结点 ---> 左子树 ---> 右子树
  2. 中序遍历:左子树---> 根结点 ---> 右子树
  3. 后序遍历:左子树 ---> 右子树 ---> 根结点
  4. 层次遍历:只需按层次遍历即可

       另外,根据遍历的策略,即“是不是一条道走到黑”而分为深度遍历(DFS)和广度遍历(BFS)。对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次,那就是深度遍历。而深度遍历适用于前序、中序和后序;广度遍历适用于层次遍历。

  1. 前序遍历:根结点 ---> 左子树 ---> 右子树  DFS
  2. 中序遍历:左子树---> 根结点 ---> 右子树   DFS
  3. 后序遍历:左子树 ---> 右子树 ---> 根结点  DFS
  4. 层次遍历:只需按层次遍历即可                 BFS

       可以看出这个序主要是针对根节点来说的,先遍历根节点就是先序遍历(前序遍历),后遍历根节点就是后序遍历,中间到根节点就是中序遍历。二叉树遍历可以使用递归也可以使用迭代,递归的这里不讨论(递归损耗资源),只讨论迭代。而迭代一般使用队列或者堆栈实现。

       一般倒序用堆栈, 正序用队列。

       DFS里面最复杂的是后续遍历,这里用堆栈。直接看代码:       

func postorderTraversal(root *TreeNode) (res []int) {
    stk := []*TreeNode{}
    var prev *TreeNode
    for root != nil || len(stk) > 0 {
        for root != nil {
            stk = append(stk, root)
            root = root.Left
        }
        root = stk[len(stk)-1]
        stk = stk[:len(stk)-1]
        // 该节点是叶子节点 或者 该节点的右孩子已遍历过
        if root.Right == nil || root.Right == prev {
            res = append(res, root.Val)
            prev = root
            root = nil
        } else {
            // 该节点还有右孩子因此要把它入队,暂不能遍历
            stk = append(stk, root)
            root = root.Right
        }
    }
    return
}

其他的先序遍历、中序遍历的原理都和这个差不多。可以思考一下怎么写。

层次遍历和上面的DFS不一样,输出和我们看各节点的顺序一致,应该用队列,其实是BFS的思路。代码如下:

func levelOrder(root *TreeNode) [][]int {
    var ans [][]int
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        level_size := len(queue)
        var level_element []int
        for i := 0; i < level_size; i++ {
            node := queue[0]
            queue = queue[1:]
            if node != nil {
              level_element = append(level_element, node.Val)
            } else {
                continue
            }
            if i == level_size -1 {
                // the last element
                ans = append(ans, level_element)
            }
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
    }
    return ans
}

最后,再来个拓展,请写出一棵二叉树的右视图。提示:可以使用层次遍历,每层的最后一个元素就是最右边的一个元素。

参考:

1. 力扣(LeetCode)中序遍历

2. 力扣(LeetCode)后序遍历

3. 力扣(LeetCode)前序遍历​​​​​

4. 力扣(LeetCode)层次遍历

5. 力扣(LeetCode)二叉树右视图

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值