二叉树:修订间差异
外观
Page creation by admin bot |
Page update by admin bot |
||
第1行: | 第1行: | ||
{{DISPLAYTITLE:二叉树}} | |||
'''二叉树'''(Binary | '''二叉树'''(Binary Tree)是计算机科学中最基础且重要的[[数据结构]]之一,广泛应用于算法设计、数据库索引、文件系统等领域。它是一种每个节点最多有两个子节点的树形结构,这两个子节点通常被称为'''左子节点'''和'''右子节点'''。 | ||
== 基本概念 == | == 基本概念 == | ||
=== 定义 === | === 定义 === | ||
二叉树是满足以下条件的[[树 (数据结构)|树]]: | |||
* | * 每个节点最多有两个子节点(左子节点和右子节点)。 | ||
* | * 子节点有明确的左右顺序之分(即使只有一个子节点,也必须指明是左还是右)。 | ||
数学上可以递归定义为: | |||
<math>T = \begin{cases} | <math>T = \begin{cases} | ||
\emptyset & \text{空树} \\ | \emptyset & \text{空树} \\ | ||
(r, | (r, T_L, T_R) & \text{根节点为 } r \text{,左子树为 } T_L \text{,右子树为 } T_R | ||
\end{cases}</math> | \end{cases}</math> | ||
=== 术语 === | === 术语 === | ||
* '''根节点''' | * '''根节点'''(Root):没有父节点的顶层节点 | ||
* ''' | * '''叶节点'''(Leaf):没有子节点的节点 | ||
* '''内部节点''' | * '''内部节点''':至少有一个子节点的非根节点 | ||
* '''深度''' | * '''深度''':从根到该节点的唯一路径的边数 | ||
* '''高度''' | * '''高度''':从该节点到最深叶节点的最长路径的边数 | ||
<mermaid> | <mermaid> | ||
第27行: | 第27行: | ||
A((根节点)) --> B((左子节点)) | A((根节点)) --> B((左子节点)) | ||
A --> C((右子节点)) | A --> C((右子节点)) | ||
B --> D(( | B --> D((叶节点)) | ||
B --> E(( | B --> E((叶节点)) | ||
C --> F(( | C --> F((叶节点)) | ||
</mermaid> | </mermaid> | ||
== 二叉树类型 == | == 二叉树类型 == | ||
=== | === 满二叉树 === | ||
每一层的节点都达到最大数量,即第<math>i</math>层有<math>2^{i-1}</math>个节点。 | |||
=== | === 完全二叉树 === | ||
除最后一层外,其他层节点都满,且最后一层节点从左向右连续排列。 | |||
=== 二叉搜索树(BST) === | === 二叉搜索树(BST) === | ||
对于任意节点: | |||
* 左子树所有节点的值 < 当前节点的值 | |||
* 右子树所有节点的值 > 当前节点的值 | |||
== | == 基本操作 == | ||
=== | === 遍历方式 === | ||
二叉树有四种基本遍历方式(以下示例代码使用Python实现): | |||
==== 前序遍历 ==== | |||
== | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
def preorder(root): | def preorder(root): | ||
if root: | if root: | ||
print(root. | print(root.val) # 访问根节点 | ||
preorder(root.left) | preorder(root.left) # 遍历左子树 | ||
preorder(root.right) | preorder(root.right) # 遍历右子树 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== 中序遍历 ==== | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
def inorder(root): | def inorder(root): | ||
if root: | if root: | ||
inorder(root.left) | inorder(root.left) # 遍历左子树 | ||
print(root. | print(root.val) # 访问根节点 | ||
inorder(root.right) | inorder(root.right) # 遍历右子树 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== 后序遍历 ==== | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
def postorder(root): | def postorder(root): | ||
if root: | if root: | ||
postorder(root.left) | postorder(root.left) # 遍历左子树 | ||
postorder(root.right) | postorder(root.right) # 遍历右子树 | ||
print(root. | print(root.val) # 访问根节点 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | ==== 层序遍历 ==== | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
from collections import deque | from collections import deque | ||
def level_order(root): | def level_order(root): | ||
queue = deque([root] | if not root: | ||
return | |||
queue = deque([root]) | |||
while queue: | while queue: | ||
node = queue.popleft() | node = queue.popleft() | ||
print(node. | print(node.val) | ||
if node.left: queue.append(node.left) | if node.left: | ||
if node.right: queue.append(node.right) | queue.append(node.left) | ||
if node.right: | |||
queue.append(node.right) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== | === 插入与删除 === | ||
以二叉搜索树为例: | |||
=== | <syntaxhighlight lang="python"> | ||
class TreeNode: | |||
def __init__(self, val): | |||
self.val = val | |||
self.left = None | |||
self.right = None | |||
def insert(root, val): | |||
if not root: | |||
return TreeNode(val) | |||
if val < root.val: | |||
root.left = insert(root.left, val) | |||
else: | |||
root.right = insert(root.right, val) | |||
return root | |||
def delete(root, val): | |||
if not root: | |||
return None | |||
if val < root.val: | |||
root.left = delete(root.left, val) | |||
elif val > root.val: | |||
root.right = delete(root.right, val) | |||
else: | |||
if not root.left: | |||
return root.right | |||
if not root.right: | |||
return root.left | |||
# 找到右子树的最小节点 | |||
temp = root.right | |||
while temp.left: | |||
temp = temp.left | |||
root.val = temp.val | |||
root.right = delete(root.right, temp.val) | |||
return root | |||
</syntaxhighlight> | |||
== 实际应用 == | |||
=== 表达式树 === | |||
用于表示数学表达式,其中: | 用于表示数学表达式,其中: | ||
* 内部节点是运算符 | * 内部节点是运算符 | ||
* | * 叶节点是操作数 | ||
<mermaid> | <mermaid> | ||
第132行: | 第148行: | ||
+ --> 5((5)) | + --> 5((5)) | ||
</mermaid> | </mermaid> | ||
表示表达式:< | 表示表达式:<code>(2 + 5) * 3</code> | ||
=== 哈夫曼编码 === | |||
用于数据压缩,通过构建最优二叉树实现高效编码。 | |||
=== | === 数据库索引 === | ||
许多数据库系统使用B树、B+树(二叉树的扩展)来加速数据检索。 | |||
== 复杂度分析 == | == 复杂度分析 == | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ | |+ 二叉树操作时间复杂度 | ||
! 操作 !! 平均情况 !! 最坏情况 | ! 操作 !! 平均情况 !! 最坏情况 | ||
|- | |- | ||
| 查找 || <math>O(\log n)</math> | | 查找 || <math>O(\log n)</math> || <math>O(n)</math> | ||
|- | |- | ||
| 插入/删除 || <math>O(\log n)</math> || <math>O(n)</math> | | 插入 || <math>O(\log n)</math> || <math>O(n)</math> | ||
|- | |||
| 删除 || <math>O(\log n)</math> || <math>O(n)</math> | |||
|- | |- | ||
| 遍历 || <math>O(n)</math> || <math>O(n)</math> | | 遍历 || <math>O(n)</math> || <math>O(n)</math> | ||
第150行: | 第172行: | ||
== 进阶话题 == | == 进阶话题 == | ||
== | * '''平衡二叉树''':AVL树、红黑树等,通过旋转操作保持平衡 | ||
1. | * '''线索二叉树''':利用空指针存储遍历信息 | ||
* '''二叉堆''':用于实现优先队列 | |||
== 练习题 == | |||
1. 实现一个函数判断两棵二叉树是否相同 | |||
2. 计算二叉树的最大深度 | 2. 计算二叉树的最大深度 | ||
3. | 3. 将有序数组转换为平衡二叉搜索树 | ||
4. 实现二叉树的序列化与反序列化 | |||
{{数据结构导航}} | |||
[[Category:数据结构]] | |||
[[Category:树结构]] | |||
[[Category:计算机科学]] | [[Category:计算机科学]] | ||
[[Category: | [[Category:面试技巧]] | ||
[[Category: | [[Category:数据结构基础]] |
2025年5月12日 (一) 00:29的最新版本
二叉树(Binary Tree)是计算机科学中最基础且重要的数据结构之一,广泛应用于算法设计、数据库索引、文件系统等领域。它是一种每个节点最多有两个子节点的树形结构,这两个子节点通常被称为左子节点和右子节点。
基本概念[编辑 | 编辑源代码]
定义[编辑 | 编辑源代码]
二叉树是满足以下条件的树:
- 每个节点最多有两个子节点(左子节点和右子节点)。
- 子节点有明确的左右顺序之分(即使只有一个子节点,也必须指明是左还是右)。
数学上可以递归定义为:
术语[编辑 | 编辑源代码]
- 根节点(Root):没有父节点的顶层节点
- 叶节点(Leaf):没有子节点的节点
- 内部节点:至少有一个子节点的非根节点
- 深度:从根到该节点的唯一路径的边数
- 高度:从该节点到最深叶节点的最长路径的边数
二叉树类型[编辑 | 编辑源代码]
满二叉树[编辑 | 编辑源代码]
每一层的节点都达到最大数量,即第层有个节点。
完全二叉树[编辑 | 编辑源代码]
除最后一层外,其他层节点都满,且最后一层节点从左向右连续排列。
二叉搜索树(BST)[编辑 | 编辑源代码]
对于任意节点:
- 左子树所有节点的值 < 当前节点的值
- 右子树所有节点的值 > 当前节点的值
基本操作[编辑 | 编辑源代码]
遍历方式[编辑 | 编辑源代码]
二叉树有四种基本遍历方式(以下示例代码使用Python实现):
前序遍历[编辑 | 编辑源代码]
def preorder(root):
if root:
print(root.val) # 访问根节点
preorder(root.left) # 遍历左子树
preorder(root.right) # 遍历右子树
中序遍历[编辑 | 编辑源代码]
def inorder(root):
if root:
inorder(root.left) # 遍历左子树
print(root.val) # 访问根节点
inorder(root.right) # 遍历右子树
后序遍历[编辑 | 编辑源代码]
def postorder(root):
if root:
postorder(root.left) # 遍历左子树
postorder(root.right) # 遍历右子树
print(root.val) # 访问根节点
层序遍历[编辑 | 编辑源代码]
from collections import deque
def level_order(root):
if not root:
return
queue = deque([root])
while queue:
node = queue.popleft()
print(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
插入与删除[编辑 | 编辑源代码]
以二叉搜索树为例:
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def insert(root, val):
if not root:
return TreeNode(val)
if val < root.val:
root.left = insert(root.left, val)
else:
root.right = insert(root.right, val)
return root
def delete(root, val):
if not root:
return None
if val < root.val:
root.left = delete(root.left, val)
elif val > root.val:
root.right = delete(root.right, val)
else:
if not root.left:
return root.right
if not root.right:
return root.left
# 找到右子树的最小节点
temp = root.right
while temp.left:
temp = temp.left
root.val = temp.val
root.right = delete(root.right, temp.val)
return root
实际应用[编辑 | 编辑源代码]
表达式树[编辑 | 编辑源代码]
用于表示数学表达式,其中:
- 内部节点是运算符
- 叶节点是操作数
表示表达式:(2 + 5) * 3
哈夫曼编码[编辑 | 编辑源代码]
用于数据压缩,通过构建最优二叉树实现高效编码。
数据库索引[编辑 | 编辑源代码]
许多数据库系统使用B树、B+树(二叉树的扩展)来加速数据检索。
复杂度分析[编辑 | 编辑源代码]
操作 | 平均情况 | 最坏情况 |
---|---|---|
查找 | ||
插入 | ||
删除 | ||
遍历 |
进阶话题[编辑 | 编辑源代码]
- 平衡二叉树:AVL树、红黑树等,通过旋转操作保持平衡
- 线索二叉树:利用空指针存储遍历信息
- 二叉堆:用于实现优先队列
练习题[编辑 | 编辑源代码]
1. 实现一个函数判断两棵二叉树是否相同 2. 计算二叉树的最大深度 3. 将有序数组转换为平衡二叉搜索树 4. 实现二叉树的序列化与反序列化