【算法】二叉树的遍历

二叉树的四种遍历方式:

  • 前序遍历:先访问根节点,然后前序遍历左子树和右子树;
  • 中序遍历:中序遍历根结点的左子树,然后访问根节点,最后中序遍历根节点的右子树;
  • 后序遍历:后序遍历根节点的左子树和右子树,最后访问根节点;
  • 层序遍历:从根节点从上往下逐层遍历,在同一层按从左到右的顺序遍历。

二叉树结点的定义:

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

一、递归解法

(一)前序遍历

def preorderTraversal(root):
    res = []
    if root:
        res.append(root.val)
        res += preorderTraversal(root.left)
        res += preorderTraversal(root.right)
    return res

(二)中序遍历

def inorderTraversal(root):
    res = []
    if root:
        res += inorderTraversal(root.left)
        res.append(root.val)
        res += inorderTraversal(root.right)
    return res

(三)后序遍历

def postorderTraversal(root):
    res = []
    if root:
        res += postorderTraversal(root.left)
        res += postorderTraversal(root.right)
        res.append(root.val)
    return res

二、非递归解法

(一)前序遍历

def preorderTraversal(root):
    res = []

    stack = []
    p = root
    # 退出循环的条件是结点为空且栈为空
    while p or len(stack):
		# 迭代访问左孩子,并入栈
        while p:
            res.append(p.val) 
            stack.append(p) 
            p = p.left 
            
		# 直到当前结点没有左孩子,退栈,转向当前结点的右孩子
        if len(stack):
            p = stack.pop()
            p = p.right

    return res

(二)中序遍历

def inorderTraversal(root):
    res = []
    
    stack = []
    p = root
    while p or len(stack):
    	# 迭代左孩子入栈
        while p:
            stack.append(p)
            p = p.left
            
        # 直到当前结点没有左孩子,退栈并访问,转向当前结点的右孩子
        if len(stack):
            p = stack.pop()
            res.append(p.val)
            p = p.right
    return res

(三)后序遍历

def postorderTraversal(root):
    res = []

    stack = []
    p = root
    last = None # 标记上一次访问的结点
    while p or len(stack):
    	# 迭代左孩子入栈
        while p:
            stack.append(p)
            p = p.left
		
		# 当前结点没有左孩子,或左孩子已经访问过
        if len(stack):
            p = stack.pop() 
            
            # 当前结点没有右孩子,或右孩子已经访问过
            if not p.right or p.right == last: 
                res.append(p.val) # 访问当前结点
                last = p
                p = None # 继续退栈,并且避免当前结点重复入栈
                
            # 有右孩子,且没访问过
            else:
                stack.append(p) # 则当前结点入栈,先转向右孩子
                p = p.right
                
    return res

三、层序遍历

给定二叉树: [3,9,20,null,null,15,7]
   3
   / \
  9 20
     / \
  15 7

返回:
  [3,9,20,15,7]

def levelOrder(root):
    res = []

    if root:
        queue = [root]
        while len(queue):
            node = queue.pop(0)
            res.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
    
    return res

给定二叉树: [3,9,20,null,null,15,7]
   3
   / \
  9 20
     / \
  15 7

返回:
  [[3],
  [9,20],
  [15,7]]

def levelOrder(root):
    res = []

    if root:
        queue = [root]
        last = root # 记录当前层最右边的元素
        tmp = []
        while len(queue):
            node = queue.pop(0)
            tmp.append(node.val)

            if node.left:
                nlast = node.left # 记录下一层最右边的元素
                queue.append(node.left)

            if node.right:
                nlast = node.right
                queue.append(node.right)
                
            # 当当前层最右边的元素出队时,说明将要开始遍历下一层的元素了
            if last == node: 
                last = nlast
                res.append(tmp)
                tmp = []

    return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值