侧边栏壁纸
博主头像
BvBeJ的小站 博主等级

行动起来,活在当下

  • 累计撰写 23 篇文章
  • 累计创建 1 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录
Go

Go语言实现二叉树非递归遍历的三种方式

BvBeJ
2025-03-28 / 0 评论 / 0 点赞 / 6 阅读 / 0 字

以下是Go语言实现二叉树非递归遍历的三种方式(前序、中序、后序),结合栈的特性实现,并附详细注释说明:


一、前序遍历(根-左-右)

核心逻辑:利用栈暂存右子节点,优先处理根节点和左子树
参考实现

func preorderTraversal(root *TreeNode) []int {
    var res []int
    if root == nil { return res }
    stack := []*TreeNode{root} // 初始化栈,根节点入栈

    for len(stack) > 0 {
        // 弹出栈顶元素(当前根节点)
        cur := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        res = append(res, cur.Val) // 先访问根节点

        // 先压右子节点(保证左子树先处理)
        if cur.Right != nil {
            stack = append(stack, cur.Right)
        }
        if cur.Left != nil {
            stack = append(stack, cur.Left)
        }
    }
    return res
}

二、中序遍历(左-根-右)

核心逻辑:通过栈回溯左子树路径,再处理右子树
参考实现

func inorderTraversal(root *TreeNode) []int {
    var res []int
    stack := []*TreeNode{}
    cur := root

    for len(stack) > 0 || cur != nil {
        // 将左子树全部入栈
        for cur != nil {
            stack = append(stack, cur)
            cur = cur.Left
        }
        // 弹出最深层左节点
        cur = stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        res = append(res, cur.Val) // 访问当前节点

        // 转向右子树
        cur = cur.Right
    }
    return res
}

三、后序遍历(左-右-根)

核心逻辑:使用双栈反转输出顺序,实现逆向存储
参考实现

func postorderTraversal(root *TreeNode) []int {
    var res []int
    if root == nil { return res }
    stack1 := []*TreeNode{root} // 主栈
    stack2 := []*TreeNode{}    // 辅助栈

    // 主栈按根-左-右顺序入栈,辅助栈反向存储
    for len(stack1) > 0 {
        cur := stack1[len(stack1)-1]
        stack1 = stack1[:len(stack1)-1]
        stack2 = append(stack2, cur) // 存入辅助栈

        // 左子节点先入主栈(后弹出)
        if cur.Left != nil {
            stack1 = append(stack1, cur.Left)
        }
        if cur.Right != nil {
            stack1 = append(stack1, cur.Right)
        }
    }

    // 辅助栈逆序输出(实际顺序左-右-根)
    for i := len(stack2)-1; i >= 0; i-- {
        res = append(res, stack2[i].Val)
    }
    return res
}

关键实现差异对比

遍历方式 核心操作 栈使用特点
前序 根节点先访问,右子节点先入栈 单栈,弹出即访问
中序 左子树全部入栈后回溯,再处理右子树 单栈,需要指针跟踪未处理节点
后序 主栈按根-左-右入栈,辅助栈反向存储实现顺序反转 双栈协同,空间复杂度O(n)

代码示例数据结构

二叉树节点定义(需在代码前声明):

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

扩展说明

  1. 时间复杂度:三种遍历均为O(n),每个节点入栈出栈各一次
  2. 空间复杂度:前序和中序为O(h)(h为树高),后序为O(n)
  3. 应用场景
    • 前序:复制树结构、表达式前缀表示
    • 中序:二叉搜索树排序输出
    • 后序:内存释放、表达式后缀计算

若需要更高效的遍历(如Morris算法),可参考空间复杂度O(1)的非栈实现。

0

评论区