研习代码 day12 | 二叉树的递归遍历&&非递归遍历(迭代)

一、二叉树的前序遍历

        1.1 题目

        给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

示例 5:

输入:root = [1,null,2]
输出:[1,2]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

        1.2 题目链接

        144.二叉树的前序遍历

        1.3 解题思路和过程想法

        (1)解题思路

        1)递归:另需开辟一个递归函数。(递归函数的参数和返回值+终止条件+单层递归的逻辑)
        2)易理解的非递归:要处理的就是当前结点。
        3)统一形式的非递归:整体思路也是利用栈的属性,逆向压栈,最后弹出得出最终结果。但是“在要处理的结点放入栈之后,紧接着放入一个空指针作为标记”:其实就是在每个“小树”的根结点入栈后,放一个空指针在其后端作为标记——毕竟每一课小树都一定会有根结点,便于后续以合适的节奏弹出结点。

        (2)过程想法:

        递归是简单的,但想通其底层用栈的原理是难的。

        1.4 代码

        1.4.1 递归
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def Traverse(self,root:TreeNode,res:list):
        # 前序遍历:根左右
        if root:
            res.append(root.val)
            self.Traverse(root.left,res)
            self.Traverse(root.right,res)
        else:
            return 

    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 用来存结果的列表
        res = []

        self.Traverse(root,res)

        return res
        1.4.2 非递归(迭代)--用栈遍历(易理解)
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 利用栈凭借非递归方式实现前序遍历
        mystack = []
        res = []

        # 根结点 ---> 弹出 ---> 右结点 ---> 左结点 ---> 弹出 ---> 弹出
        # 最后从结果数组中获取的就是:根左右
        mystack.append(root)
        while len(mystack):
            # 弹出根结点,将其加入结果列表
            node = mystack[-1]
            mystack.pop()
            if node:
                res.append(node.val)
                # 压入右结点
                if node.right:
                    mystack.append(node.right)
                # 压入左结点
                if node.left:
                    mystack.append(node.left)

        return res
        1.4.3 统一形式的非递归
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 统一的迭代方式实现遍历
        mystack = []
        res = []

        # 保证二叉树非空,以进入下列循环
        if root:
            mystack.append(root)
        # 利用栈来正序输出:根左右 ----> 逆向压栈:右左根
        while len(mystack):
            node = mystack[-1]
            if node:
                mystack.pop()
                # 右
                if node.right:
                    mystack.append(node.right)
                # 左
                if node.left:
                    mystack.append(node.left)
                # 根 + 用 None 标记未处理结点
                mystack.append(node)
                mystack.append(None)
            else:
                # 若当前结点为空,则先弹出该空指针;再弹出未处理的“根”结点
                mystack.pop()
                node = mystack[-1]
                mystack.pop()
                res.append(node.val)

        return res

二、二叉树的后序遍历

        2.1 题目

        给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 

示例 1:

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点的数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

        2.2 题目链接

        145.二叉树的后序遍历

        2.3 解题思路和过程想法 

        (1)解题思路

        1)递归:另需开辟一个递归函数。(递归函数的参数和返回值+终止条件+单层递归的逻辑)
        2)易理解的非递归:要处理的就是当前结点。
        3)统一形式的非递归:整体思路也是利用栈的属性,逆向压栈,最后弹出得出最终结果。但是“在要处理的结点放入栈之后,紧接着放入一个空指针作为标记”:其实就是在每个“小树”的根结点入栈后,放一个空指针在其后端作为标记——毕竟每一课小树都一定会有根结点,便于后续以合适的节奏弹出结点。

        (2)过程想法:

        递归是简单的,但想通其底层用栈的原理是难的。

        2.4 代码

        2.4.1 递归
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postTraverse(self,root:TreeNode,res:list):
        # 后续遍历:左右根
        if root:
            self.postTraverse(root.left,res)
            self.postTraverse(root.right,res)
            res.append(root.val)
        else:
            return 

    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 用来存储结果
        res = []

        self.postTraverse(root,res)

        return res
        2.4.2 非递归(迭代) ---用指针遍历(易理解)
class Solution:

    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        mystack = []
        # 用来存储结果
        res = []

        mystack.append(root)
        # 根结点 ---> 压栈+弹出 ---> 左结点 ---> 压栈 ---> 右结点 ---> 压栈 ---> 弹出全部
        # 最终结果:根右左 ---> 逆转:左右根

        while len(mystack):
            node = mystack[-1]
            mystack.pop()
            if node:
                if node.left:
                    mystack.append(node.left)
                if node.right:
                    mystack.append(node.right)
                res.append(node.val)
        
        res.reverse()

        return res
        2.4.3 统一形式的非递归
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 统一的迭代方式实现遍历
        mystack = []
        res = []

        # 保证二叉树非空,以进入下列循环
        if root:
            mystack.append(root)
        # 利用栈来正序输出:左右根 ----> 逆向压栈:根右左
        while len(mystack):
            node = mystack[-1]
            if node:
                mystack.pop()
                # 根 + 用 None 标记未处理结点
                mystack.append(node)
                mystack.append(None)
                # 右
                if node.right:
                    mystack.append(node.right)
                # 左
                if node.left:
                    mystack.append(node.left)
            else:
                # 若当前结点为空,则先弹出该空指针;再弹出未处理的“根”结点
                mystack.pop()
                node = mystack[-1]
                mystack.pop()
                res.append(node.val)

        return res

三、二叉树的中序遍历

        3.1 题目

        给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

        3.2 题目链接

        94.二叉树的中序遍历

        3.3 解题思路和过程想法

        (1)解题思路

        1)递归:另需开辟一个递归函数。(递归函数的参数和返回值+终止条件+单层递归的逻辑)
        2)非递归:基于中序遍历的思想,要处理的就是当前结点的方式行不通,使用指针+栈的方式。先一直向左(一直压栈),直到为空,则弹出根结点,并加入右孩子。
        3)统一形式的非递归:整体思路也是利用栈的属性,逆向压栈,最后弹出得出最终结果。但是“在要处理的结点放入栈之后,紧接着放入一个空指针作为标记”:其实就是在每个“小树”的根结点入栈后,放一个空指针在其后端作为标记——毕竟每一课小树都一定会有根结点,便于后续以合适的节奏弹出结点。

        (2)过程想法:

        递归是简单的,但想通其底层用栈的原理是难的。

        3.4 代码

        3.4.1 递归
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inTraverse(self,root:TreeNode,res:list):
        # 中序遍历:左根右
        if root:
            self.inTraverse(root.left,res)
            res.append(root.val)
            self.inTraverse(root.right,res)
        else:
            return

    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 用来存储结果
        res = []

        self.inTraverse(root,res)

        return res
3.4.2 非递归(迭代)---用栈遍历(易理解)
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 用来存储结果
        res = []
        # 用指针来遍历结点
        cur = root
        # 用栈来记录已遍历的结点
        mystack = []

        while cur or len(mystack):
            # 一直向左
            if cur:
                mystack.append(cur)
                cur = cur.left
            # 左边走不下去,就弹出;并将右压栈
            else:
                node = mystack[-1]
                mystack.pop()
                res.append(node.val)
                cur = node.right

        return res
         3.4.3 统一形式的非递归
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 统一的迭代方式实现遍历
        mystack = []
        res = []

        # 保证二叉树非空,以进入下列循环
        if root:
            mystack.append(root)
        # 利用栈来正序输出:左根右 ----> 逆向压栈:右根左
        while len(mystack):
            node = mystack[-1]
            if node:
                mystack.pop()
                # 右
                if node.right:
                    mystack.append(node.right)
                # 根 + 用 None 标记未处理结点
                mystack.append(node)
                mystack.append(None)
                # 左
                if node.left:
                    mystack.append(node.left)
            else:
                # 若当前结点为空,则先弹出该空指针;再弹出未处理的“根”结点
                mystack.pop()
                node = mystack[-1]
                mystack.pop()
                res.append(node.val)

        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值