二叉树的中序遍历,每层遍历,以及Z字形遍历

leetcode中,二叉树也是一块重点,对于树结构衍生出的问题,一般用递归的方法会比较多。
在这里插入图片描述
如上图的二叉树:
中序遍历:左-根-右的顺序,结果是[4,2,5,1,6,3]
每层遍历:从最上面那层往下面读,结果是[1,2,3,4,5,6]
Z字形遍历:和每层遍历差不多,只是走Z字,结果是[1,3,2,4,5,6]

二叉树的中序遍历

对于二叉树的中序遍历,就是左-根-右这种遍历顺序。
有递归和迭代写法:非递归就用栈来实现

        res, stack = [], []
        while True:
            while root:
                stack.append(root)
                root = root.left
            if not stack:
                return res
            node = stack.pop()
            res.append(node.val)
            root = node.right

我们看栈的情况,while true保证了直到栈为空(if not stack)的时候我们结束循环,这时候我们已遍历栈中所有所有元素。
while root让我们一直会保证左边的元素会先进栈,直到左边没有元素为止,.pop()弹出后入栈的,后入栈的是最底层的左侧元素。
比如第一次while true循环,1,2,4先进stack栈,4的左边没有元素,所以把4先出栈到res里,再将root更新成4的右孩子,现在stack: [1,2], res: [4]
第二次while true循环,4的右孩子不存在,会执行2出栈,将root更新成2的右孩子,现在stack: [1], res: [4,2]
第三次 while true循环, 5进stack栈,5的左边没有元素,5出栈到res里,将root更新成5的右孩子,stack: [1], res:[4,2,5]

这个的思想就是,while root和root=root.left保证了左子树的元素纷纷统统入栈,当我们要考虑一个元素的右孩子时,就说明这个元素已经被我们出栈了。一个元素的右孩子也为空就说明我们已经走到了最左侧,应该往上一层考虑了。这里的root = node.right很巧妙(下一次循环与这一次计算结果有关,迭代)。

递归写法:

def inorderTraversal1(self, root):
    res = []
    self.helper(root, res)
    return res
    
def helper(self, root, res):
    if root:
        self.helper(root.left, res)
        res.append(root.val)
        self.helper(root.right, res)

这个还是挺直观的,按左-根右的顺序调用函数helper(),函数调用栈会是helper(1.left), append(1), helper(1.right),再对helper(1.left)的函数调用栈进行分析,总是左-根-右的顺序。

每层遍历

要求输出的是一个二维列表,每个元素是每层元素所组成的列表。
比如示例就应该输出[[1],[2,3],[4,5,6]]

def levelOrder(self, root):
    if not root:
        return []
    ans, level = [], [root]
    while level:
        ans.append([node.val for node in level])
        temp = []
        for node in level:
            temp.extend([node.left, node.right])
        level = [leaf for leaf in temp if leaf]  #只把非None的孩子添加进去
    return ans

思想就是开枝散叶的思想,有两个列表很关键,一个是结果列表res存我们的结果,一个是每层元素列表level存每层的树结点元素。只要这层不是空的,我就把这层元素添加进ans里,再用extend方法将孩子列表做好(对每个本层元素都开枝散叶它下层元素),并更新层元素列表。

Z字形遍历

要求输出的是一个二维列表,每个元素是每层元素所组成的列表。
比如示例就应该输出[[1],[3,2],[4,5,6]]

思想和上述一样,就是加个flag对第偶数次遍历反序

    def zigzagLevelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        ans, level = [], [root]
        flag = 1
        while level:
            ans.append([node.val for node in level][::flag]) #偶数次反序
            temp = []
            for node in level:
                temp.extend([node.left, node.right])
            level = [leaf for leaf in temp if leaf]  #只把非None的孩子添加进去
            flag *= -1
        return ans

总结一下:
1.对于树的中序遍历,递归好写很多,迭代不太直观
2.对于树的每层遍历,extend一次加多个元素,level = [leaf for leaf in temp if leaf] 这个写的不错
3.在Z字形遍历中,flag的妙用,我一开始想的话就会用counter,循环一次加1,如果偶数次就逆向输出,代码太不简洁了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值