代码随想录算法训练营第十四天| LeetCode144. 二叉树的前序遍历、LeetCode145. 二叉树的后序遍历、LeetCode94. 二叉树的中序遍历

二叉树的种类

        在我们解题过程中二叉树有两种主要的形式:满二叉树和完全二叉树。

满二叉树

        满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。

        如图所示:

        这棵二叉树为满二叉树,也可以说深度为k,有2^k-1个节点的二叉树。

完全二叉树

        什么是完全二叉树?

        完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1)  个节点。

二叉搜索树

        前面介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是一个有序树

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序树

        下面这两棵树都是搜索树

平衡二叉搜索树

        平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

        最后一棵 不是平衡二叉树,因为它的左右两个子树的高度差的绝对值超过了1。

二叉树的存储方式

        二叉树可以链式存储,也可以顺序存储。

        那么链式存储方式就用指针, 顺序存储的方式就是用数组。

        顾名思义就是顺序存储的元素在内存是连续分布的,而链式存储则是通过指针把分布在散落在各个地址的节点串联一起。

        链式存储如图:

        链式存储是大家很熟悉的一种方式,那么我们来看看如何顺序存储呢?

        其实就是用数组来存储二叉树,顺序存储的方式如图:

        用数组来存储二叉树如何遍历的呢?

        如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。

二叉树的遍历方式

二叉树主要有两种遍历方式:

  1. 深度优先遍历:先往深走,遇到叶子节点再往回走。
  2. 广度优先遍历:一层一层的去遍历。

这两种遍历是图论中最基本的两种遍历方式

那么从深度优先遍历和广度优先遍历进一步拓展,才有如下遍历方式:

  • 深度优先遍历
    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)
  • 广度优先遍历
    • 层次遍历(迭代法)

在深度优先遍历中:有三个顺序,前中后序遍历, 有同学总分不清这三个顺序,经常搞混,我这里教大家一个技巧。

这里前中后,其实指的就是中间节点的遍历顺序,只要大家记住 前中后序指的就是中间节点的位置就可以了。

看如下中间节点的顺序,就可以发现,中间节点的顺序就是所谓的遍历方式

  • 前序遍历:中左右
  • 中序遍历:左中右
  • 后序遍历:左右中

如下图:

二叉树的定义 

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

 一、LeetCode144. 二叉树的前序遍历

        1:题目描述(144. 二叉树的前序遍历

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

 

        2:解题思路

        解法一:递归法

# 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 preorderTraversal(self, root):
        # # 前序遍历:中左右
        # 使用递归遍历,需要确定的三个条件
        # 1:确定递归函数的参数和返回值
        # 2:确定终止条件
        # 3:确定单层递归的逻辑
        def traversal(cur, res):
            if cur == None:               # 当节点为空,返回到上个节点
                return
            res.append(cur.val)           # 将父节点添加到res
            traversal(cur.left, res)      # 遍历左节点
            traversal(cur.right, res)     # 遍历右节点
        res = []
        cur = root
        traversal(cur, res)
        return res

         解法二:迭代法

# 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 preorderTraversal(self, root):
        # # 前序遍历:中左右
        # 迭代法
        # 使用栈来实现
        stack = []                  # 定义一个栈
        res = []                    # 存遍历节点的数组
        if not root:
            return res
        stack.append(root)          # 将根节点添加到栈中
        while stack:
            node = stack.pop()      # 将栈中最后一个节点弹出
            res.append(node.val)    # 并把节点的值加入到res中
            # 然后将节点的左右子节点添加到栈中
            # 因为前序遍历的顺序是:中左右,栈是先进后出,所以需要先将右节点先入栈,在将左节点入栈
            if node.right:
                stack.append(node.right)       # 当右节点不为空时,先将右节点入栈
            if node.left:
                stack.append(node.left)        # 当左节点不为空时,再将左节点入栈
        return res

二、LeetCode145. 二叉树的后序遍历

        1:题目描述(145. 二叉树的后序遍历

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

        2:解题思路

        解法一:递归法

# 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 postorderTraversal(self, root):
        # 后序遍历:左右中
        # 使用递归遍历,需要确认三个条件
        # 1:确定递归函数的参数和返回值
        # 2:确定终止条件
        # 3:确定单层递归的逻辑
        def traversal(cur, res):
            if cur == None:
                return
            traversal(cur.left, res)
            traversal(cur.right, res)
            res.append(cur.val)           
        
        res = []
        traversal(root, res)
        return res

        解法二:迭代法

# 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 postorderTraversal(self, root):
        # 后序遍历:左右中
        # 迭代法
        # 使用栈来实现
        stack = []
        res = []
        if not root:
            return res
        # 因为后序遍历的顺序是:左右中,可以将顺序改为中右左,最后再将得到的res进行一个翻转即可
        stack.append(root)                    # 将根节点root加入栈stack中
        while stack:
            node = stack.pop()                # 将根节点从栈中弹出
            res.append(node.val)              # 将根节点的值,添加到数组res中
            # 我们添加到res的顺序是中右左,栈是先进后出,所以先将左节点入栈,再将右节点入栈
            if node.left:
                stack.append(node.left)       # 左节点不为空,则入栈
            if node.right:
                stack.append(node.right)      # 右节点不为空,则入栈
        # 此时res中的结果是按照中右左的顺序进行遍历得到的结果,需要将res中的元素进行翻转
        res.reverse()                         # 翻转数组
        return res

三、LeetCode94. 二叉树的中序遍历

         1:题目描述(94. 二叉树的中序遍历

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

        2:解题思路

        解法一:递归法

# 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 inorderTraversal(self, root):
        # 中序遍历:左中右
        def traversal(cur, res):
            if cur == None:
                return 
            traversal(cur.left, res)          # 遍历左节点
            res.append(cur.val)               # 左节点遍历完成后,将根节点加入res中
            traversal(cur.right, res)         # 遍历右节点

        res = []
        traversal(root, res)
        return res

        解法二:迭代法

# 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 inorderTraversal(self, root):
        # 中序遍历:左中右
        # 迭代法
        # 使用栈和指针来实现,栈用来存放遍历过的元素,指针进行遍历二叉树
        stack = []
        res = []
        cur = root
        if not root:                # 当根节点为空,直接返回[]
            return res
        while cur or stack:
            # 先迭代访问最底层的左子树节点
            if cur != None:            # 当前节点不为空
                stack.append(cur)      # 将当前节点入栈
                cur = cur.left         # 再指向当前节点的左节点
            # 到达最底层左子节点后,处理栈顶元素
            else:                      # 当前节点为空了
                cur = stack.pop()      # 从栈中弹出节点
                res.append(cur.val)    # 将节点的值加入到res中
                cur = cur.right        # 在将cur指向当前节点的右节点
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值