(三)二叉树的深度优先遍历(前中后序)的递归实现

(三)二叉树的深度优先遍历(前中后序)的递归实现

首先, 先实现树, 构造树后, 才能遍历树的节点;
这里提供根据,层序输入列表构建 二叉树;
空节点, 使用 - 1 表示;

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

import collections
def levelInputCreateTree(nums: list) -> TreeNode:
    root =  TreeNode(nums[0])  # 将数组首元素 作为根节点;
    que = collections.deque([root])  #  调用 collections 中的 deque, 并且将根节点 输入到其中;

    i, lenNum = 1,  len(nums)  # i 从数组中的下标1开始, 遍历输入到队列中;

    #  迭代法, 创建二叉树
    while i < lenNum:
        cur_Node = que.popleft()  # 弹出双端队列的 左边队首的元素;  该弹出的元素是一个树的节点, 作为当前的节点;

        leftVal, rightVal = nums[i],  nums[i + 1]  if i + 1 < lenNum else -1  #  如果下标 i + 1 超过数组下标, 则赋值为 -1 ;

        if  leftVal != -1 :  #  输入的数组中的 -1 代表此处是 空节点;  或者超出数组下标;
            leftNode = TreeNode(leftVal)  #  将左值 初始化为树的 一个节点;
            cur_Node.left = leftNode  #  将 上述的 左值树节点 赋值为 curNode 的左子树;
            que.append(leftNode)      # 将该节点入队, 便于后序出队, 为他添加子树,也即子节点;

        if  rightVal != -1:
            rightNode = TreeNode(rightVal)
            cur_Node.right = rightNode
            que.append(rightNode)

        i += 2
    return root

if __name__ == "__main__":
    print("--- please input a  level order list to create A Binary Tree---")
    # strip 去除输入中最左边右边的 空格;  split 将输入按空格分割, 返回一个列表;
    #  map 是将input() 输入的字符串 转换为 int 整型;
    nums = list(map(int, input().strip().split()))
    print("you  level order Tree input list : ", nums)
    # 将输入的 层序 列表 建成树;
    tree1 = levelInputCreateTree(nums)

    # 按照 先序遍历树;
    print(" preorder Traversal the Tree: \n", preOrderTraversal(tree1))

# 18 7 11 3 4 5 6

1. 递归的三要素

  1. 递归函数的输出类型 和 输入参数;

  2. 递归的终止条件, 即满足何时递归到底, 到底后, 可以从从底往上返回了;

  3. 单层递归中, 应该执行的步骤;

1.1 递归函数的三要素

以前序遍历的 递归 举例:

  1. 递归函数的输出类型, 递归函数的输入参数:
    输入参数 root , 表示当前遍历到的节点;
    输出参数: 无, 最终结果 在递归函数外面;

  2. 递归的终止条件:
    递归终止的条件为碰到空节点。

  3. 单层递归的步骤:
    首先将 root 节点的值加入答案,
    然后递归调用 preorder(root.left) 来遍历 root 节点的左子树,
    最后递归调用 preorder(root.right) 来遍历 root 节点的右子树即可。

2. 深度优先遍历的递归实现

2.1 前序遍历的递归实现

二叉树先序遍历的过程中,首先访问根节点,然后依次遍历其左右子树,左右子树的访问过程递归进行。

该过程是「自顶向下」的,不论是「递归」还是「迭代」,对任意一个节点,当且仅当其父节点遍历完成后,才能遍历该节点及其子树。

适用场景: 已知父节点信息, 求子节点的信息;

因此,实际问题求解中,若需要基于已求出的「父节点」信息,自顶向下地求解各个「子节点」的信息;
此时可考虑对二叉树进行先序遍历,在遍历的过程中维护所求出的信息。

例如:给定一棵二叉树,判断其是否为对称二叉树。

def preOrderTraversal(root: TreeNode) -> list:
    result = []

    def traversal(root: TreeNode)-> None:    # 1. 递归的输入参数, 以及输出参数
        if root == None :          # 2. 递归终止条件: 若当前节点是个空节点, 说明递归到底了, 结束,  开始从后往前返回;
            return

        result.append(root.val)       # 3. 单层递归需要执行的操作 , 由于是前序遍历, 故先取出当前节点的数值, 然后遍历当前节点它的左子树, 在遍历当前节点的右子树;
        traversal(root.left)
        traversal(root.right)

    traversal(root)      # 递归入口;
    return  result

2.2 中序遍历的递归实现

二叉树中序遍历的过程中,首先访问左子树,然后访问根节点,最后访问右子树,左右子树的访问过程递归进行。

适用场景: 求二叉搜索树的相关问题

由于「二叉搜索树」中,任意节点的值均比其左子树中各个节点的值大,均比其右子树中各个节点的值小,且左右子树同样满足此性质,因此中序遍历是常用于遍历二叉搜索树,且得到的中序遍历序列「严格递增」。

因此,若实际问题中给定二叉搜索树,可基于中序遍历进行问题求解。

例如:给定一棵二叉树,判断其是否是二叉搜索树。

def inorderTraversal(root: TreeNode) -> list:
        result = []

        def traversal(root: TreeNode) -> None:  # 1. 递归函数的 输入参数, 输出参数
            if root == None:  # 2. 递归函数的 终止条件
                return
                # 3.  单层递归中, 应该执行的步骤
            traversal(root.left)  # 中序遍历,先遍历左子树;
            result.append(root.val)  # 然后, 保存当前节点值;
            traversal(root.right)  # 之后遍历右子树;

        traversal(root)  # 递归函数入口
        return result

2.3 后序遍历的递归实现

二叉树后序遍历的过程中,首先访问左子树,然后访问右子树,最后访问根节点,左右子树的访问过程递归进行。

与二叉树的先序遍历不同,二叉树后序遍历的过程是「自底向上」的,不论是「递归」还是「迭代」,对任意一个节点,当且仅当其左子树和右子树均遍历完成后,才能遍历该节点。

适用场景: 根据左右子树的信息, 求出当前节点(或称为父节点)的信息;
因此,实际问题求解中,若需要基于已求出的「左子树和右子树」的信息,自底向上地求解各个「当前节点」的信息,此时可考虑对二叉树进行后序遍历,在遍历的过程中维护所求出的信息。例如:

给定一棵二叉树,判断其是否是平衡二叉树;

给定一棵二叉树与两个节点,返回这两个节点的最近公共祖先节点。

def postorderTraversal(root: TreeNode) -> list:
        result = []

        def traversal(root: TreeNode)-> None:  # 1.  递归的输入 ,输出参数
            if root == None:                   # 2. 递归的终止条件
                return
                                                # 3.  单层递归中,应该执行的步骤;
            traversal(root.left)
            traversal(root.right)
            result.append(root.val)

        traversal(root)
        return result

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值