二叉树
二叉树
一、二叉树的基本概念
二叉树(Binary Tree)是一种树形数据结构,它的每个节点最多只能有两个子节点,分别称为左子节点和右子节点。可以把它类比成 “每个家长最多只能有两个孩子” 的家族树。
关键术语:
- 根节点:树的最顶层节点,没有父节点。
- 叶子节点:没有任何子节点的节点。
- 节点的度:节点拥有的子节点数量(二叉树中最多为 2)。
- 树的深度 / 高度:从根节点到最远叶子节点的路径上的节点数。
- 满二叉树:所有非叶子节点都有两个子节点,且所有叶子节点在同一层。
- 完全二叉树:除最后一层外,每一层节点数都达到最大值,最后一层的叶子节点靠左排列。
二、二叉树的经典计算方法与公式(全是递归,学会这个公式就可以)
1. 二叉树的基本定义(Python 实现)
先定义二叉树节点的类,这是所有计算的基础:
1 | class TreeNode: |
2. 经典计算方法与公式
(0)计算二叉树的单侧高度(深度)
- 公式 / 逻辑:二叉树单侧的高度 = 无子节点则停止更新。
- Python 代码:
1 | def get_right_height(node): |
(1)计算二叉树的高度(深度)
- 公式 / 逻辑:二叉树的高度 = max (左子树高度,右子树高度) + 1(递归思想,叶子节点高度为 1)。
- Python 代码:
1 | def tree_height(root: TreeNode) -> int: |
(2)计算二叉树的节点总数
- 公式 / 逻辑:总节点数 = 左子树节点数 + 右子树节点数 + 1(当前节点)。
1 | def count_nodes(root: TreeNode) -> int: |
(3)计算二叉树的叶子节点数
-
公式 / 逻辑:
叶子节点 = 若当前节点是叶子(无左右子节点)则为 1;否则 = 左子树叶子数 + 右子树叶子数。
-
Python 代码:
1 | def count_leaf_nodes(root: TreeNode) -> int: |
(4)完全二叉树的节点数(优化公式)
对于完全二叉树,无需递归遍历所有节点,可利用特性优化计算:
-
公式:
设完全二叉树的高度为 h:
-
若右子树的高度 = h-1 → 左子树是满二叉树,节点数 = 2^(h-1) + 右子树节点数;
-
若右子树的高度 = h-2 → 右子树是满二叉树,节点数 = 2^(h-2) + 左子树节点数。
(满二叉树高度为 k 时,节点数 = 2^k -1)
-
-
Python 代码:
1 | def count_complete_tree_nodes(root: TreeNode) -> int: |
二叉树有三种常见的遍历方式:
1. 先序遍历
原则:根左右(先访问根,再访问左子树,最后访问右子树)
- 通俗解释:遇到一个节点,立刻记下它的值,然后再去处理左边的分支,左边处理完了,再去处理右边。
- 访问顺序:
- 访问根节点。
- 先序遍历左子树。
- 先序遍历右子树。
- 举例:
假如有一个树:先序遍历的结果是:A -> B -> D -> E -> C -> F1
2
3
4
5A
/ \
B C
/ \ \
D E F
(过程:A -> 进左树(B -> 进左树(D) -> 进右树(E)) -> 回到A的右树(C -> 进右树(F)))
2. 中序遍历
原则:左根右(先访问左子树,再访问根,最后访问右子树)
- 通俗解释:先把左边的所有子节点处理完了,才回头记下当前节点的值,然后再去处理右边。
- 访问顺序:
- 中序遍历左子树。
- 访问根节点。
- 中序遍历右子树。
- 举例:
同样的树:中序遍历的结果是:D -> B -> E -> A -> C -> F1
2
3
4
5A
/ \
B C
/ \ \
D E F
(过程:进A的左树(进B的左树(D) -> B -> 进B的右树(E)) -> A -> 进A的右树(C -> 进C的右树(F)))
(注意:因为C没有左子树,所以直接访问C,然后进它的右树F)
3. 后序遍历
原则:左右根(先访问左子树,再访问右子树,最后访问根)
- 通俗解释:确保这个节点的左孩子和右孩子都被记录完了,最后才记录这个节点本身。
- 访问顺序:
- 后序遍历左子树。
- 后序遍历右子树。
- 访问根节点。
- 举例:
同样的树:后序遍历的结果是:D -> E -> B -> F -> C -> A1
2
3
4
5A
/ \
B C
/ \ \
D E F
(过程:处理A的左树(处理B的左树(D) -> 处理B的右树(E) -> B) -> 处理A的右树(处理C的右树(F) -> C) -> A)
如何快速记忆?
为了帮助你记忆,我们可以把根看作核心,把左看作“左边全部”,把右看作“右边全部”。
- 先序:根最先出现(根左右)。
- 中序:根在中间出现(左根右)。
- 后序:根最后出现(左右根)。
它们有什么用?
这三种遍历方式在不同的应用场景下有不同的用途:
- 先序遍历:用于复制一棵树(因为你先拷贝了根,才知道把左右子树挂在哪里),或者用于输出表达式的前缀表示。
- 中序遍历:在二叉搜索树(BST)中,中序遍历的结果是一个递增的有序序列。这是它最重要的特性。
- 后序遍历:用于删除树(你得先把孩子删了,才能删父亲,否则孩子找不到了),或者用于计算树的高度、自底向上的计算(比如计算文件夹占用的磁盘空间)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 This is a 部落格 of outbreak_sen!


