【备忘】二叉树遍历的迭代实现

二叉树的递归遍历很简单清晰,但是迭代遍历的话是有一定难度的,尤其是迭代中序遍历,因此在这里对二叉树三种前中后序遍历的迭代实现做一个小总结。

先序迭代

先序迭代利用额外的一个栈来辅助实现,类似于BFS,但与BFS不同的是,每次压栈需要先压入右子节点,再压左子节点,下面以Golang描述。

func preorderTraversal(root *TreeNode) (res []int) {
    if root == nil{
        return
    }
    stack := []*TreeNode{root}
    for len(stack) != 0{
        cur := stack[len(stack)-1]
        stack = stack[0: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
}

后序遍历

之所以不先写中序,是因为后序迭代的代码其实可以很容易地由先序改来,我们知道先序是根左右的遍历顺序,其中“左”、“右”是根据压入栈的顺序来调整的,因此我们可以通过调整压栈顺序来得到 根右左的遍历次序,得到了根右左,那么后序遍历的左右根就可以由根右左逆序得到,下面以Golang来描述过程:

func postorderTraversal(root *TreeNode) (res []int) {
    if root == nil{
        return
    }
    stack := []*TreeNode{root}
    for len(stack)!=0{
        cur := stack[len(stack)-1]
        stack = stack[0:len(stack)-1]
        res = append(res, cur.Val)
        if cur.Left != nil{
            stack = append(stack, cur.Left)
        }
        if cur.Right != nil{
            stack = append(stack, cur.Right)
        }
    }
    for i,j:=0,len(res)-1; i<j;{
        temp := res[i]
        res[i] = res[j]
        res[j] = temp
        i ++
        j --
    }

    return
}

中序遍历

中序遍历相对来说较难一些,但也是利用一个辅助栈来完成,基本思想是首先将所有左子节点沿着根向下遍历入栈直到没有左子节点,之后开始向外弹栈,弹栈的过程中再考虑元素的右子树;

具体实现如下:

func inorderTraversal(root *TreeNode) []int {
    res, stack := []int{}, []*TreeNode{}
    if root != nil{
        for root != nil || len(stack) != 0{
            if root != nil{ //当前节点压栈,再继续检查左子树
                stack = append(stack, root)
                root = root.Left
            }else{ // 左子树走到了尽头,将当前节点回退到父节点,将父节点写入结果集,同时栈弹出,再继续检查右子树
                root = stack[len(stack)-1]
                res = append(res, stack[len(stack)-1].Val)
                stack = stack[0:len(stack)-1]
                root = root.Right
            }
        }
    }
    return res
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值