二叉树的遍历

Posted ditingz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的遍历相关的知识,希望对你有一定的参考价值。

参考链接:https://segmentfault.com/a/1190000016674584

前言

二叉树的前中后序遍历是面试考察中一个重要的点。而递归方法是最简单实现的,所以要信手拈来。非递归方法更要加以掌握。前序就是根-左-右,中序是左-根-右,后序是左-右-根。
有两种通用的遍历树的策略:
深度优先搜索(DFS)
在这个策略中,我们采用深度作为优先级,以便从跟开始一直到达某个确定的叶子,然后再返回根到达另一个分支。
深度优先搜索策略又可以根据根节点、左孩子和右孩子的相对顺序被细分为前序遍历,中序遍历和后序遍历。
宽度优先搜索(BFS)
我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到。

层次遍历

题目链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/er-cha-shu-de-ceng-ci-bian-li-by-leetcode/

非递归,用队列实现(其实自己想了会能不能用递归结果自己不会。。。

看了下题解,它的递归实现其实用了深度优先。

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if root==None:
            return []
        result = [[root.val]]
        quene = [(root,1)]
        while(quene):
            root,count = quene.pop(0)
            if root.left:
                quene.append((root.left,count+1))
                if count+1>len(result):
                    result.append([root.left.val])
                else:
                    result[count].append(root.left.val)
            if root.right:
                quene.append((root.right,count+1))
                if count+1>len(result):
                    result.append([root.right.val])
                else:
                    result[count].append(root.right.val)
        return result

 

前序遍历

题目描述:链接 https://leetcode-cn.com/problems/binary-tree-preorder-traversal/description/?utm_source=LCUS&utm_medium=ip_redirect_q_uns&utm_campaign=transfer2china
技术图片

然鹅,很简单的递归算法我自己实现的时候都会出错。。。还是太太菜

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        list = []
        self.preorderHelp(list,root)
        return list
    def preorderHelp(self,list,root):
        if root==None:
            return None
        else:
            list.append(root.val)
            self.preorderHelp(list,root.left)
            self.preorderHelp(list,root.right)

 

非递归,使用栈。先压右子树再压左子树

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        stack = [root,]
        if root==None:
            return result
        while(stack):
            root = stack.pop()
            result.append(root.val)
            if root.right!=None:
                stack.append(root.right)
            if root.left!=None:
                stack.append(root.left)
        return result

 

中序遍历

链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

递归方法:

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        self.inordefHelper(result,root)
        return result
    def inordefHelper(self,result,root):
        if root==None:
            return
        self.inordefHelper(result,root.left)
        result.append(root.val)
        self.inordefHelper(result,root.right)

 非递归采用两层循环:按照根节点左子树顺序压栈,然后再改变指针,对右子树采用同样的方法

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        stack = []
        if root==None:
            return []
        while(stack or root!=None):
            while(root!=None):
                stack.append(root)
                root = root.left
            root = stack.pop()
            result.append(root.val)
            root = root.right
        return result

 

后序遍历:

链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/submissions/

递归写法

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        if root==None:
            return result
        self.postHelper(result,root)
        return result
    def postHelper(self,result,root):
        if root==None:
            return
        self.postHelper(result,root.left)
        self.postHelper(result,root.right)
        result.append(root.val)

 

非递归写法:(对已经访问过的右子树做标记,根据后续的特点,若访问过右子树肯定根节点的右节点是刚被访问过的,用指针添加新的节点),不明白的话看参考链接哦

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        stack = []
        pre = None
        if root==None:
            return result
        while(stack or root!=None):
            while(root!=None):
                stack.append(root)
                root = root.left
            root = stack[-1]
            if root.right==None or root.right==pre:
                root = stack.pop()
                result.append(root.val)
                pre = root
                root = None
            else:
                root = root.right
        return result

 

针对后序遍历还有个简化方法

双栈法
前序遍历比较简单,因为是先访问根
1.用一个栈实现 根->右->左 的遍历
2.用另一个栈将遍历顺序反过来,使之变成 左->右->根
实现代码:

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        stack1 = [root,]
        stack2 = []
        if root == None:
            return []
        while(stack1):
            root = stack1.pop()
            stack2.append(root)
            if root.left!=None:
                stack1.append(root.left)
            if root.right!=None:
                stack1.append(root.right)
        while(stack2):
            root = stack2.pop()
            result.append(root.val)
        return result

双栈简化:直接每次插入时将元素插入到头部class Solution:

    def postorderTraversal(self, root: TreeNode) -> List[int]:
        result = []
        stack1 = [root,]
        stack2 = []
        if root == None:
            return []
        while(stack1):
            root = stack1.pop()
            result.insert(0,root.val)
            if root.left!=None:
                stack1.append(root.left)
            if root.right!=None:
                stack1.append(root.right)
        return result

以上是关于二叉树的遍历的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的遍历

讲透学烂二叉树:二叉树的遍历图解算法步骤及JS代码

二叉树(2.二叉树的遍历和实现)

根据二叉树的前序遍历和中序遍历构建二叉树的c语言完整代码

通过遍历序列构造二叉树(扩展二叉树的先序先序和中序后序和中序层序和中序)附可执行完整代码

代码题— 二叉树的层次遍历