【专题讲解】树专题:二叉树的四种遍历

Leetcode 112 路径总和

又是一道二叉树的题目,这次我们来总结二叉树的深度搜索,广度搜索:

二叉树的遍历

  • 广度优先遍历breadth first traversal:又称层次遍历,从树的根节点(root)开始,从上到下,从左到右遍历整个树的节点。
  • 深度优先遍历depth first traversal:对于一颗二叉树,深度优先遍历是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
    • 深度优先遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。
    1. 先序遍历(preorder):根节点->左子树->右子树,
    2. 中序遍历(inorder):左子树->根节点->右子树,
    3. 后序遍历(postorder):左子树->右子树->根节点。

在这里插入图片描述
我们以这幅图为例子进行分析三种遍历的区别。

  • 层次遍历(BFS):0123456789
  • 先序遍历:0137849256(根左右)
  • 中序遍历:7381940526(左中右)
  • 后序遍历:7839415620(左右中)
    # 先序遍历
    def preorder(self, root):
        if not root:
            return 
        print(root.val) # 取出来值!!
        self.preorder(node.left)
        self.preorder(node.right)

    # 中序遍历
    def inorder(self, root):
        if not root:
            return
        self.inorder(root.left)
        print(root.val) # 取出来值!!
        self.inorder(root.right)
        
    # 后序遍历
    def postorder(self, root):
        if not root:
            return
        self.postorder(root.left)
        self.postorder(root.right)
        print(root.val) ## 取出来值
            
    # 广度优先(层次)遍历        
    def levelOrder(self,root):
	    if not root:
	        return
	     queue = collections.deque()
	     queue.append(root)
	     while queue:
	         node = queue.popleft()
	         # 进行相关操作
	         print(node.val)
	         if node.left:
	             queue.append(node.left)
	         if node.right:
	             queue.append(node.right)



更新2020.03.30 DFS的非递归方法

	#非递归实现前序遍历
	# 先序遍历是先访问节点,然后再将节点入栈
	def preOrderNonRec(root):
	    if not root:
	        return
	    stack = []
	    cur = root
	    while cur or stack:
	        while cur:
	            print(cur.val)
	            stack.append(cur)
	            cur = cur.left #一直往下找左子树

	        cur = stack.pop()
	        cur = cur.right
	 
	# 中序遍历是先入栈,然后节点弹出栈后再访问。
	def midOrderNonRec(root):
	    if not root:
	        return
	    stack = []
	    cur = root
	    while cur or stack:
	        while cur:
	            stack.append(cur)
	            cur = cur.left #一直往下找左子树
	        cur = stack.pop()
	        print(cur.val)
	        cur = cur.right
	 
	#非递归实现后序遍历
	'''
	在这种遍历中,每个根节点都要经过三次:
	第一次遇到它时要立即转去处理其左子树,
	第二次从左子树经由它转去处理右子树,
	第三次从右子树回来才应该处理根节点数据,然后返回上一层。
	'''
	def postOrderNonRec(root):
	    if not root:
	        return
	    stack = []
	    cur = root
	    while cur or stack:
	        while cur:
	            stack.append(cur)
	            if cur.left:
                    cur = cur.left
                else:
                    cur = cur.right
	        cur = stack.pop() 
	        print(cur.val)

	        if stack and stack[-1].left == cur: #栈不空且当前节点是栈顶的左子节点,那么应当继续去访问栈顶的右子节点
	            cur = stack[-1].right
	        else:
	            cur = None #没有右子树或右子树遍历完毕,强迫退栈
	            
	'''
	也可以反转前序遍历的方式实现,因为后序是右->左->中,先序是中->左->右
	'''
    def postorderTraversal(self, root):
        ans, queue, cur = [], [], root
        while queue or cur:
            while cur:
                queue.append(cur)
                ans.append(cur.val)
                cur = cur.right
            cur = queue.pop()
            cur = cur.left
        return ans[::-1]      

Leetcode 112 路径总和

又是一道二叉树的题目,这次我们来总结二叉树的深度搜索,广度搜索:
介绍完搜索,切入正题,leetcode112 题路径总和
在这里插入图片描述显然这是一个深度优先的算法的题目。需要按照深度遍历整个树。
依然按照递归思想求解。设置递归的条件,root节点的左右子节点都None时判断整个路径和是否单组要求。

class Solution(object):
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False
        sum -= root.val
        if not root.right and not root.left: ## 搜索到了底部
            return sum == 0
        return self.hasPathSum(root.right,sum) or self.hasPathSum(root.left,sum)  
        # 继续在两侧进行搜索

其实,做为树的递归题目是非常有套路可循的,因为树有两个分支,所以在递归里也有两个分支,一般是通过right == None and left == Noneright or left来实现分支的。只要明白了这一点,递归函数就不会很难设计。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值