Python - 代码随想录算法训练营第十四天 | 理论基础、递归遍历、迭代遍历、统一迭代
前言
上周做个兼职,没有顾上写代码,罪过,这周抓紧一些补起来。
从现在开始进入二叉树部分的内容。
原神实在是令人沉迷,我要脱离出来,不能耽误学习!!!
理论基础
二叉树 指 树上的每个节点的子节都不超过2。
二叉树的种类
关于理论基础,要明确两个概念:
- 满二叉树
- 完全二叉树
满二叉树
通俗的讲,就是每一层节点都是满的,最底下一层的节点的子节点都是0。
完全二叉树
通俗的说,是指:二叉树的节点从左到右填满(最后一层可以不满),不能出现中间突然缺一个的现象。
二叉搜索树 (有序树)
每个节点带数值。左节点的数 < 根节点 < 右节点的数
平衡二叉搜索树
又被称为AVL(Adelson-Velsky and Landis)树,左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
二叉树的存储方式
二叉树可以链式存储,也可以顺序存储。 一般用链式。
二叉树的遍历方式
- 深度优先遍历
- 前序遍历(递归法,迭代法)
- 中序遍历(递归法,迭代法)
- 后序遍历(递归法,迭代法)
- 广度优先遍历
- 层次遍历(迭代法)
- 层次遍历(迭代法)
二叉树的定义
class TreeNode:
def __init__(self, val, left = None, right = None):
self.val = val
self.left = left
self.right = right
递归遍历 (前中后)
自己调用自己就是递归。
题目链接
可以做一做leetcode上三道题目,分别是:
144.二叉树的前序遍历(opens new window)
145.二叉树的后序遍历(opens new window)
94.二叉树的中序遍历(opens new window)
思路:
-
这个类中的 preorderTraversal 方法接收一个二叉树的根节点 root 作为输入,并返回一个列表,其中包含了按照前序遍历顺序访问的所有节点的值。
-
在方法的实现中,首先进行了一个条件判断,如果传入的根节点为空,则直接返回一个空列表,因为空树没有任何节点需要遍历。
-
然后,通过递归调用 preorderTraversal 方法来分别对左子树和右子树进行前序遍历,将得到的左子树节点值列表和右子树节点值列表存储在 left 和 right 中。
-
最后,将根节点的值、左子树节点值列表和右子树节点值列表合并起来,构成最终的前序遍历结果,并返回该结果。
代码如下:
# 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: TreeNode) -> List[int]:
if not root:
return []
left = self.preorderTraversal(root.left)
right = self.preorderTraversal(root.right)
return [root.val] + left + right # 前序遍历
# 中序遍历
#return left + [root.val] + right
# 后序遍历
#return left + right + [root.val]
迭代遍历
在这里我们用栈来完成。
已知栈的特点是后进先出。
前序遍历 (中左右)
- 我们遍历树时不可能越过中间节点,每次先碰到的是中间节点。
- 接下来希望获得左节点,由栈的特点可知。放入顺序应该是右左,只有这样才能够先拿出左节点。
)
代码
# 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: TreeNode) -> List[int]:
if not root:
return []
stack = [root]
result = []
while stack:
node = stack.pop()
result.append(node.val)
if node.right: #右节点入栈
stack.append(node.right)
if node.left: #左节点入栈
stack.append(node.left)
return result
中序遍历 (左中右)
- 先找到最左下角的节点,这是我们返回的结果里的第一个节点
- 弹出加入结果列表后;栈里留着的是中间节点cur,可以直接加入结果列表;
- 按照刚才的步骤处理cur.right
代码:
# 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: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = []
result = []
cur = root
while cur or stack:
#找到最左下角的节点
if cur:
stack.append(cur)
cur = cur.left
#开始处理包括stack最后一个节点的小单元
else:
cur = stack.pop()
result.append(cur.val)
cur = cur.right
return result
后序遍历(左右中)
- 可以参考前序遍历的思路
- 先得到 中右左 然后将列表倒序即可
代码
# 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: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = [root]
result = []
while stack:
node = stack.pop()
result.append(node.val)
if node.left: #左节点入栈
stack.append(node.left)
if node.right: #右节点入栈
stack.append(node.right)
return result[::-1]
统一迭代
思路:
代码如下:
总结
-
待改进
-
收获