二叉排序树
定义
二叉排序树 (Binary Sort Tree, BST),又称二叉查找树 (Binary Search Tree),是一棵具有下列性质的二叉树:
- 若其左子树不空,则左子树上所有结点的值均小于其根结点的值。
- 若其右子树不空,则右子树上所有结点的值均大于其根结点的值。
- 其左、右子树也分别为二叉排序树。
- 树中没有键值相同的结点。
核心特性:对二叉排序树进行中序遍历,可以得到一个递增的有序序列。
查找
查找操作是二叉排序树的基础。从根结点开始,沿着一条路径进行查找。
-
查找过程:
- 从根结点
p开始,比较待查关键字key与p->data。 - 若
key == p->data,则查找成功。 - 若
key < p->data,则在p的左子树中继续查找。 - 若
key > p->data,则在p的右子树中继续查找。 - 若查找到空指针(
p == NULL),则说明树中不存在该关键字,查找失败。
- 从根结点
-
实现:可以是递归的,也可以是非递归的。其查找路径的长度决定了查找的时间复杂度。
插入
插入操作是向二叉排序树中添加一个新元素,同时保持其二叉排序树的性质。
-
插入过程:
- 从根结点开始,执行与查找类似的过程,为待插入的关键字
key寻找插入位置。 - 如果树为空,则新结点作为根结点。
- 如果树不为空,查找过程必将因遇到空指针而失败。该空指针的位置就是新结点的插入位置。
- 将新结点作为叶子结点插入。
- 从根结点开始,执行与查找类似的过程,为待插入的关键字
-
特点:新插入的结点一定是叶子结点。
构造
构造一棵二叉排序树,就是从一个空树开始,依次将待插入的元素序列中的每个元素通过插入操作加入树中。
- 构造过程:给定一个关键字序列
(k_1, k_2, ..., k_n),从一棵空树开始,依次执行Insert(k_i)操作,直到所有关键字都插入树中。 - 重要性质:对于同一个关键字序列,不同的插入顺序可能得到不同形态的二叉排序树。
- 例如,序列
(45, 24, 53, 12, 37, 93)会生成一棵相对平衡的树。 - 而序列
(12, 24, 37, 45, 53, 93)会生成一棵单支树(右斜树),查找效率退化为顺序查找。
- 例如,序列
删除
删除操作是二叉排序树中最复杂的操作,需要根据待删除结点 p 的子树情况分三种情况讨论:
-
p是叶子结点:- 直接删除该结点,并将其父结点的相应指针域置为
NULL。这是最简单的情况。
- 直接删除该结点,并将其父结点的相应指针域置为
-
p只有左子树或只有右子树:- 删除结点
p,并将其唯一的子树(左子树或右子树)直接链接到p的父结点上,替代p的位置。
- 删除结点
-
p既有左子树又有右子树:- 这是最复杂的情况。为保持二叉排序树的性质,不能直接删除
p。 - 方法:在
p的子树中找到一个可以替代p的结点,用该替代结点的值覆盖p的值,然后删除那个替代结点。 - 替代结点的选择(二选一):
- 中序前驱:
p的左子树中值最大的结点。 - 中序后继:
p的右子树中值最小的结点。
- 中序前驱:
- 以中序后继为例的删除步骤:
a. 找到
p的右子树中最小的结点s(即从p的右孩子出发,一直向左走到尽头)。 b. 将s的值赋给p。 c. 此时问题转化为删除结点s。由于s是其所在子树的最小结点,它最多只有一个右孩子(不可能有左孩子)。因此,删除s的问题就转化为了上述情况 1 或 2。
- 这是最复杂的情况。为保持二叉排序树的性质,不能直接删除
效率指标
二叉排序树的查找、插入、删除等操作的效率都取决于树的高度(或深度)h。
| 操作 (Operation) | 平均情况 (Average Case) | 最坏情况 (Worst Case) |
|---|---|---|
| 查找 (Search) | ||
| 插入 (Insertion) | ||
| 删除 (Deletion) |
- 平均情况:当关键字序列是随机的时,生成的二叉排序树趋向于平衡,其高度 。此时,各项操作的效率都接近 。
- 最坏情况:当关键字序列本身有序或逆序时,生成的二叉排序树会退化成线性链表(单支树),其高度 。此时,各项操作的效率退化为 ,与顺序查找无异。
为了解决最坏情况下的性能问题,引入了平衡二叉树(Balanced Binary Tree),如 AVL 树和红黑树,它们通过在插入和删除后进行调整来确保树的高度始终保持在 的量级。
其他性质
n 个结点二叉查找树的形态个数
由 n 个互不相同的结点所能构成的二叉排序树的形态个数,是一个与卡特兰数 (Catalan Number) 相关的问题。
-
推导思路:
- 设 为用 n 个结点可以构造出的不同二叉排序树的个数。
- 从 n 个结点中(不妨设为 1, 2, …, n)任取一个结点 作为根结点。
- 根据二叉排序树的定义,小于 的 个结点必须构成左子树,大于 的 个结点必须构成右子树。
- 左子树有 种形态,右子树有 种形态。根据乘法原理,以 为根的二叉排序树有 种形态。
- 由于根结点 可以是 1, 2, …, n 中的任意一个,根据加法原理,总的形态数是所有情况的总和。
-
递推公式:
其中,规定 $h(0) = 1$(表示空树有一种形态)。
- 卡特兰数公式: 该递推关系的结果即为卡特兰数 。
- 示例:计算有 3 个结点(如 {1, 2, 3})的二叉排序树形态个数。
- 所以,有 3 个结点的二叉排序树共有 5 种不同的形态。