二叉树理论基础篇
本文介绍了二叉树的基础知识,包括满二叉树、完全二叉树、二叉搜索树、平衡二叉搜索树以及二叉树的存储方式和遍历方式。
🌳 二叉树的种类包括满二叉树和完全二叉树。
🌿 满二叉树是只有度为0和度为2的节点,并且度为0的节点在同一层上的二叉树。
🌲 完全二叉树的每层节点数都达到最大值,除了最底层可能没有填满。
🔎 二叉搜索树是有序树,左子树的节点值都小于根节点的值,右子树的节点值都大于根节点的值。
⚖️ 平衡二叉搜索树的左右子树高度差不超过1,且左右子树都是平衡二叉树。
💾 二叉树可以用链式存储(指针)或顺序存储(数组)方式表示。
🌐 二叉树的遍历方式包括前序、中序、后序和层序遍历。
递归遍历
递归三要素
-
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
-
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
-
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
144. 二叉树的前序遍历 - 力扣(Leetcode)
# 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: Optional[TreeNode]) -> List[int]:
path = []
def traversal(cur, path):
if cur == None:
return
path.append(cur.val)
traversal(cur.left, path)
traversal(cur.right, path)
traversal(root, path)
return path
145. 二叉树的后序遍历 - 力扣(Leetcode)
# 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]:
path = []
def traversal(cur, path):
if cur == None:
return
traversal(cur.left, path)
traversal(cur.right, path)
path.append(cur.val)
traversal(root, path)
return path
94. 二叉树的中序遍历 - 力扣(Leetcode)
# 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]:
path = []
def traversal(cur, path):
if cur == None:
return
traversal(cur.left, path)
path.append(cur.val)
traversal(cur.right, path)
traversal(root, path)
return path
迭代遍历
迭代法主要是创建一个栈,访问某个结点就Pop,然后按照一定顺序将非空的孩子结点入栈,重复此类过程。
注意对于中序遍历要进行特殊处理,先迭代访问最底层的左子树结点,然后才能开始保存结果
# 前序遍历-迭代-LC144_二叉树的前序遍历
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
# 中序遍历-迭代-LC94_二叉树的中序遍历
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
stack = [] # 不能提前将root结点加入stack中
result = []
cur = root
while cur or stack:
# 先迭代访问最底层的左子树结点
if cur:
stack.append(cur)
cur = cur.left
# 到达最左结点后处理栈顶结点
else:
cur = stack.pop()
result.append(cur.val)
# 取栈顶元素右结点
cur = cur.right
return result
# 后序遍历-迭代-LC145_二叉树的后序遍历
class Solution:
def postorderTraversal(self, root: 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]
统一迭代
简而言之就是将节点入栈和保存结果分离开来,通过入栈的顺序区分前中后序遍历。
# 迭代法前序遍历
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
result = []
st= []
if root:
st.append(root)
while st:
node = st.pop()
if node != None:
if node.right: #右
st.append(node.right)
if node.left: #左
st.append(node.left)
st.append(node) #中
st.append(None)
else:
node = st.pop()
result.append(node.val)
return result
# 迭代法中序遍历
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
result = []
st = []
if root:
st.append(root)
while st:
node = st.pop()
if node != None:
if node.right: #添加右节点(空节点不入栈)
st.append(node.right)
st.append(node) #添加中节点
st.append(None) #中节点访问过,但是还没有处理,加入空节点做为标记。
if node.left: #添加左节点(空节点不入栈)
st.append(node.left)
else: #只有遇到空节点的时候,才将下一个节点放进结果集
node = st.pop() #重新取出栈中元素
result.append(node.val) #加入到结果集
return result
# 迭代法后序遍历
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
result = []
st = []
if root:
st.append(root)
while st:
node = st.pop()
if node != None:
st.append(node) #中
st.append(None)
if node.right: #右
st.append(node.right)
if node.left: #左
st.append(node.left)
else:
node = st.pop()
result.append(node.val)
return result
总结
- 了解了常见的二叉树分类
- 掌握了递归遍历二叉树的方法,基本清楚迭代遍历二叉树的方法,了解统一迭代遍历二叉树的方法