前言:
二叉树是数据结构中最重要的非线性结构之一,其分层特性和递归定义使其成为理解树、图等复杂结构的基础。本文将系统介绍二叉树的核心概念、分类及进阶拓展(如平衡树、B 树等),并通过 Python 代码演示关键操作的实现,帮助读者建立从理论到实践的完整认知。
一、二叉树的本质定义与核心特性
1.1 定义:
二叉树是一种分层的树状数据结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。其递归定义为:
空树是二叉树;
若 T 是非空树,则 T 由根节点、左子树 TL 和右子树 TR 组成,且 TL 和 TR 均为二叉树。
1.2 核心特性:
1、每个节点度≤2:节点的子节点数量只能是 0、1 或 2。
2、有序性:左子树和右子树是有序的(交换左右子树会形成不同的二叉树)。
3、分层结构:具有根节点(第 1 层),每一层节点最多有 2^(i-1) 个(i 为层数)。
二、二叉树的分类:从特殊到一般
2.1满二叉树
定义:除最后一层外,所有层的节点都有两个子节点,且最后一层节点全为叶子节点(无任何子节点)。
数学特征:若高度为 h,则总节点数为 2^h - 1(h≥1)。
特点:每层节点 “填满”,无空缺,适合用链式存储或完全二叉树的顺序存储。
2. 2完全二叉树
定义:除最后一层外,其余层节点数均达到最大值,且最后一层节点从左到右连续存在(不允许中间有空缺)。
关键性质:
可使用顺序存储结构(数组)高效表示,根节点索引为 0,左子节点为 2i+1
,右子节点为 2i+2
。高度为 h 的完全二叉树节点数范围:2^(h-1) ≤ n < 2^h。
2.3 平衡二叉树
定义:任意节点的左、右子树高度差不超过 1。
典型实现:
AVL 树:严格平衡,通过旋转(LL、RR、LR、RL)保持平衡,插入 / 删除时最多旋转 2 次。
红黑树:弱平衡(最长路径 ≤ 最短路径的 2 倍),通过颜色标记(红 / 黑)和少量旋转实现高效平衡,应用更广泛(如 Java 的TreeMap
)。
作用:避免退化为链表,保证搜索、插入、删除的时间复杂度为 O(log n)
三、二叉树核心操作的代码实现(Python)
3.1节点定义与树构建
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val # 节点值
self.left = left # 左子节点
self.right = right# 右子节点
# 示例:构建一棵简单二叉树
# 根节点 1
# / \
# 2 3
# / \
# 4 5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
3.2深度优先遍历(DFS)
# 前序遍历(根→左→右)
def preorder(root):
if root:
print(root.val, end=' ')
preorder(root.left)
preorder(root.right)
# 中序遍历(左→根→右)
def inorder(root):
if root:
inorder(root.left)
print(root.val, end=' ')
inorder(root.right)
# 后序遍历(左→右→根)
def postorder(root):
if root:
postorder(root.left)
postorder(root.right)
print(root.val, end=' ')
3. 3广度优先遍历(BFS,层序遍历)
return []
queue = deque([root])
result = []
while queue:
level_size = len(queue)
level = []
for _ in range(level_size):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(level)
return result
四、二叉树的进阶结构与应用
4.1 AVL 树:严格平衡的二叉搜索树
特性:左右子树高度差不超过 1,通过旋转保持平34衡。
旋转类型:
LL 旋转(左左插入):右单旋,调整失衡节点的左子3树。
RR 旋转(右右插入):左单旋,调整失衡节点的右子3树。
LR 旋转(左右插入):先左后右双旋,调整失衡节点的左子树的右子3树。
RL 旋转(右左插入):先右后左双旋,调整失衡节点的右子树的左子3树。
应用:早期数据库索引,需频繁查询但较少插入 / 删除的场景。
4.2 红黑树:高效的弱平衡树
核心规则:
节点非红即黑,根节点和叶子节点(虚拟 NULL)为黑色。
红色节点的子节点必须为黑色,任意路径上黑色节点数相同。
插入修复逻辑:若父节点为红色,根据叔叔节点颜色调整:
叔叔为黑色:通过旋转(左旋 / 右旋)调整颜色,恢复平衡。
叔叔为红色:父、叔变黑,祖父变红,递归处理祖父;
应用:Java 的TreeMap
、C++ 的std::map
、Linux 内核调度器。
4.3 B 树与 B + 树:适合磁盘存储的多叉树
B 树:
结构:每个节点包含多个键值对,子节点数介于\(m/2\)和m之间(m 为阶数)。
操作:插入时若节点满则分裂,删除时若节点不足则合并,保证树高为 (O (\log_m n)7)。
B + 树:
特性:所有数据存储在叶子节点,叶子节点通过链表连接,支持高效范围查78询。
应用:数据库索引(如 MySQL 的 InnoDB 引擎)、文件系统(如 NTFS8)。
4.4 哈夫曼树:最优前缀编码
构建步骤:将所有节点按权重排序,每次选取权重最小的两个节点作为左右子树,合并为父节点(权重为两者之和);重复直至形成单棵树,左路径编码为 0,右路径编码为 1。
import heapq
class HuffmanNode:
def __init__(self, val, freq):
self.val = val
self.freq = freq
self.left = self.right = None
def build_huffman_tree(frequencies):
heap = [HuffmanNode(char, freq) for char, freq in frequencies.items()]
heapq.heapify(heap)
while len(heap) > 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
parent = HuffmanNode(None, left.freq + right.freq)
parent.left, parent.right = left, right
heapq.heappush(heap, parent)
return heap[0]
五、总结
二叉树是理解树形结构的基石,其递归特性和分层设计为后续学习平衡树(AVL / 红黑树)、多叉树(B/B + 树)及应用算法(如哈夫曼编码)提供了理论基础。通过掌握二叉树的遍历、构建及扩展结构,可有效提升算法思维和问题解决能力,尤其在面试和实际开发(如数据库索引、数据压缩)中具有重要价值。