二叉树N叉数的前中后序遍历总结,python实现递归法和迭代法

关于二叉树的前序遍历(preoder)、中序遍历(inorder)和后序遍历(postorder),实际上只需要记住:左子节点一定在右子节点的左边(左右),所谓前中后序遍历就是根节点的位置不同,前序是根左右,中序是左根右,后序是左右根。

python代码实现,先定义树节点的类如下:

class TreeNode:
     def __init__(self, val=0, left=None, right=None):
         self.val = val
         self.left = left
         self.right = right

然后是前中后序的递归法实现,非常直观:

    # 前序遍历
    def preorderTraversal(self, root: TreeNode) -> List[int]:

        def preorder(root: TreeNode):
            if not root:
                return
            ans.append(root.val) # 根左右
            preorder(root.left)
            preorder(root.right)
        
        ans = list()
        preorder(root)
        return ans
	
	# 中序遍历
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        def inorder(root: TreeNode):
            if not root:
                return
            inorder(root.left)  # 左根右
            ans.append(root.val)
            inorder(root.right)
        
        ans = list()
        inorder(root)
        return ans
    
    # 后序遍历
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        def postorder(root: TreeNode):
            if not root:
                return
            postorder(root.left) # 左右根
            postorder(root.right)
            ans.append(root.val)
        
        ans = list()
        postorder(root)
        return ans

可以看到,实际上前中后序的递归法实现区别仅仅在于访问左右子节点和将根节点加入结果数组的顺序不同。

迭代法实现复杂一点,一般是使用一个栈,如下:

	# 前序遍历
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        if not root:
        	return ans
        stack = []
        stack.append(root)
        while stack:
            node = stack.pop()
            if node:
                if node.right:                  # 右
                    stack.append(node.right)
                if node.left:					# 左
                    stack.append(node.left)
                stack.append(node)				# 根
                stack.append(None)
            else:
                node = stack.pop()
                ans.append(node.val)
        return ans
        
    # 中序遍历
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        if not root:
        	return ans
        stack = []
        stack.append(root)
        while stack:
            node = stack.pop()
            if node:
                if node.right:					# 右
                    stack.append(node.right)
                stack.append(node)				# 根
                stack.append(None)
                if node.left:					# 左
                    stack.append(node.left)
            else:
                node = stack.pop()
                ans.append(node.val)
        return ans

	# 后序遍历
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        if not root:
        	return ans
        stack = []
        stack.append(root)
        while stack:
            node = stack.pop()
            if node:
                stack.append(node)				# 根
                stack.append(None)
                if node.right:					# 右
                    stack.append(node.right)
                if node.left:					# 左
                    stack.append(node.left)
            else:
                node = stack.pop()
                ans.append(node.val)
        return ans

可以看到,前中后序遍历的迭代写法是统一的,唯一区别就是中间的代码,只需要记住从下往上是根左右(前序)、左根右(中序)、左右根(后序)即可

对于N叉数,思路和二叉树是比较相似的。先看下N叉数的树节点定义:

# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children

589. N 叉树的前序遍历

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        def preorderTravel(root: 'Node'):
            if not root:
                return
            ans.append(root.val)
            for child in root.children:
                preorderTravel(child)
        
        ans = list()
        preorderTravel(root)
        return ans

递归写法,区别只是用for循环遍历所有子节点,而不是只遍历左右子节点。

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        if not root:
            return []
        
        stack = [root,]
        output = []            
        while stack:
            root = stack.pop()
            output.append(root.val)
            stack.extend(root.children[::-1])
                
        return output

迭代写法,这里注意入栈的是root.children[::-1],这样出栈时才是从左子树到右子树正确的顺序。

590. N 叉树的后序遍历

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        def postorderTravel(root: 'Node'):
            if not root:
                return
            for child in root.children:
                postorderTravel(child)
            ans.append(root.val)

        ans = list()
        postorderTravel(root)
        return ans

递归写法,相比前序遍历只是交换了一下位置,而N叉数没有中序遍历。

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        if not root:
            return []
        
        stack = [root,]
        output = []

        while stack:
            root = stack.pop()
            if root:
                output.append(root.val)
            for child in root.children:
                stack.append(child)
                
        return output[::-1]

迭代写法。

559. N 叉树的最大深度

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if not root:
            return 0
        elif root.children == []:
            return 1
        else:
            temp = list()
            for child in root.children:
                temp.append(self.maxDepth(child))
            return max(temp) + 1

递归,与二叉树的最大深度类似,注意要判断 root.children == [] 时深度为1。

还有一种遍历二叉树的方法,可以将空间复杂度降至O(1),名为Morris遍历,对其解释地最好的我觉得是这篇文章。

另外还有一种题,二叉树是存储成数组形式的,这时就要利用以下关系:根节点从0开始编号,对于任意一个节点 i,其左孩子编号为 2i+1,右孩子编号为 2i+2,代码如下:

#
# 对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果
# @param input int整型一维数组 -1表示Nil节点
# @return int整型二维数组
#
# 定义一个二维列表
results = [[]for i in range(3)]
class Solution:
    def binaryTreeScan(self , input ):
        # write code here
        # 前序遍历
        def preOrder(root):
            if root<len(input):
                if input[root]!=-1:
                    results[0].append(input[root])
                preOrder(root*2+1)
                preOrder(root*2+2)
        # 中序遍历
        def inOrder(root):
            if root<len(input):
                inOrder(root*2+1)
                if input[root]!=-1:
                    results[1].append(input[root])
                inOrder(root*2+2)
        # 后序遍历
        def postOrder(root):
            if root<len(input):
                postOrder(root*2+1)
                postOrder(root*2+2)
                if input[root]!=-1:
                    results[2].append(input[root])
        preOrder(0)
        inOrder(0)
        postOrder(0)
        return results

你可能感兴趣的:(二叉树,dfs,leetcode,数据结构,python,1024程序员节)