跳转至

第7章 查找

2027 王道 · 专题阅读 · 保留代码与校订注 · 与版本锁一致

第7章 查找

⚠️ 本章是考研命题的重点。 折半查找要掌握过程、判定树构造、ASL 分析;二叉排序树、平衡二叉树、红黑树要掌握概念、性质和操作。⚠️ B 树和 B+ 树是本章难点 —— B 树要求掌握插入、删除、查找的操作过程,B+ 树仅要求了解基本概念和性质。散列要掌握构造、冲突处理、成功/失败 ASL、性能分析。

回源 · PDF 第 276 页 · b_276_5

【知识树】第7章骨架

  • 基本概念:静态/动态查找表、关键字、ASL
  • 线性表查找
  • 顺序查找(一般表 / 有序表 + 哨兵)
  • 折半查找 + 判定树
  • 分块查找(索引顺序查找)
  • 树形查找
  • 二叉排序树 BST:查找、插入、删除、性能
  • 平衡二叉树 AVL:LL/RR/LR/RL 四种旋转
  • 红黑树:五条性质、插入调整
  • B 树与 B+ 树
  • 散列表:散列函数、冲突处理、ASL 与装填因子
回源 · PDF 第 276 页 · b_276_0;PDF 第 276 页 · b_276_2

7.1 查找的基本概念

什么叫查找成功和查找失败?

查找是在数据集合中寻找满足某种条件的数据元素的过程。 - 查找成功:集合中找到了满足条件的数据元素 - 查找失败:集合中不存在满足条件的数据元素

⚠️ “失败”不是算法异常,而是查找的一种正常结果;计算 ASL 时,成功查找和失败查找通常要分别统计。

回源 · PDF 第 276 页 · b_276_7;PDF 第 276 页 · b_276_8

静态查找表和动态查找表怎么分?

  • 静态查找表:仅涉及查找,无须动态修改 → 顺序查找、折半查找
  • 动态查找表:需要支持插入或删除 → 二叉排序树查找
  • ⚠️ 散列查找既可用于静态表,也可用于动态表(取决于实现)

关键字 = 唯一标识元素的数据项的值,⚠️ 基于关键字的查找应返回唯一结果。

回源 · PDF 第 277 页 · b_277_10

ASL 的定义式?

\[\mathrm{ASL} = \sum_{i=1}^{n} P_i C_i\]
  • Pᵢ:查找第 i 个元素的概率,⚠️ 等概率时 Pᵢ = 1/n
  • Cᵢ:找到第 i 个元素所需的关键字比较次数

⚠️ ASL 是衡量查找算法效率的核心指标。

回源 · PDF 第 277 页 · b_277_3;PDF 第 277 页 · b_277_13

7.2 顺序查找和折半查找

哨兵是干什么的?

int Search_Seq(SSTable ST, ElemType key) {
    ST.elem[0] = key;                              // 哨兵
    for (int i = ST.TableLen; ST.elem[i] != key; --i);   // 从后往前找
    return i;                                      // 成功返回下标,失败返回 0
}

⚠️ 引入哨兵是为了避免在循环中反复判断数组下标是否越界 —— 查找失败时循环必然在 i = 0 处终止(因为 ST.elem[0] == key),返回 0 表示失败。

💡 效果:省去边界判断,提高效率。

回源 · PDF 第 277 页 · b_277_1;PDF 第 277 页 · b_277_6

一般线性表顺序查找的 ASL?

定位第 i 个元素需比较 Cᵢ = n − i + 1 次(从表尾向前找)。 - ⚠️ 等概率下 ASL_成功 = (n+1)/2 - ⚠️ ASL_不成功 = n + 1

优化思路:⚠️ 若能预知各记录的查找概率,应按概率由大到小重排,使高频元素靠近查找起点。

优缺点:缺点是 n 较大时 ASL 大、效率低;⚠️ 优点是对存储结构无要求(顺序、链式都行),且不要求有序。⚠️ 链表只能采用顺序查找。

回源 · PDF 第 278 页 · b_278_12

有序表的顺序查找为什么失败时更快? ★1考

⚠️ 有序时,一旦发现当前元素关键字大于 key 就可以立即判定失败,无须比到表的另一端。

判定树:圆形结点是表中实际存在的元素;⚠️ 矩形结点是失败结点,n 个元素对应 n + 1 个失败结点。 ⚠️ 到达某失败结点的比较次数 = 其父结点所在的层数。

\[\mathrm{ASL}_{失败} = \frac{1+2+\cdots+n+n}{n+1} = \frac{n}{2} + \frac{n}{n+1}\]

教材例:n = 6 时 ASL_失败 = 6/2 + 6/7 = 3.86,⚠️ 比一般顺序查找的 n+1 = 7 好一些。

⚠️ 两点区别于折半查找:思想上有本质区别;⚠️ 有序表的顺序查找可用链式存储,折半查找只能顺序存储。

★ 考过 2013

回源 · PDF 第 278 页 · b_278_8

折半查找的代码和取整约定? ★1考

int Binary_Search(SSTable L, ElemType key) {
    int low = 0, high = L.TableLen - 1, mid;
    while (low <= high) {
        mid = (low + high) / 2;
        if (L.elem[mid] == key) return mid;
        else if (L.elem[mid] > key) high = mid - 1;   // 前半部分
        else low = mid + 1;                            // 后半部分
    }
    return -1;
}

⚠️ 取中间结点时向下取整或向上取整都可以,但每次查找必须采用相同的取整方式。

★ 考过 2016

回源 · PDF 第 279 页 · b_279_3

折半查找判定树的三条性质? ★2考

  • ⚠️ 查找成功的查找长度 = 从根到目的结点路径上的结点数
  • ⚠️ 查找失败的查找长度 = 从根到对应失败结点的父结点路径上的结点数
  • 任一结点的值大于其左子树所有结点、小于其右子树所有结点
  • ⚠️ n 个元素对应 n 个圆形非叶结点和 n + 1 个方形叶结点
  • ⚠️ 判定树是一棵平衡二叉树

★ 考过 2015、2017

回源 · PDF 第 280 页 · b_280_1

折半查找的 ASL 和树高? ★2考

\[\mathrm{ASL} = \frac{n+1}{n}\log_2(n+1) - 1 \approx \log_2(n+1) - 1\]
  • ⚠️ 树高 h = ⌈log₂(n+1)⌉,比较次数最多不超过判定树的高度
  • ⚠️ 时间复杂度 O(log₂n)

教材算例(11 个元素): - ASL_成功 = (1×1 + 2×2 + 3×4 + 4×4)/11 = 3 - ASL_失败 = (3×4 + 4×8)/12 = 11/3

★ 考过 2010、2023

回源 · PDF 第 280 页 · b_280_5

折半查找的两个适用条件? ★1考

  • ⚠️ 只适用于顺序存储结构,不适用于链式存储 —— 因为需要随机访问任意位置的元素才能快速定位中间元素
  • ⚠️ 要求表中元素按关键字有序排列

★ 考过 2024

回源 · PDF 第 280 页 · b_280_10

分块查找的组织方式和两个步骤? ★1考

基本思想:把查找表划分为若干子块 —— ⚠️ 块内元素可以无序,但块间必须有序(任意前一块的最大关键字小于后一块中的所有关键字);建立索引表,每个元素含对应块的最大关键字和该块的起始地址,索引表按最大关键字有序。

两步: - ① 在索引表中确定待查记录所在的块(可顺序查找或折半查找) - ② 在目标块内进行顺序查找

★ 考过 2025

回源 · PDF 第 280 页 · b_280_15

分块查找的 ASL 和最优块长?

\[\mathrm{ASL} = L_1 + L_S = \frac{b+1}{2} + \frac{s+1}{2} = \frac{s^2+2s+n}{2s}\]

(长度 n 均分为 b 块、每块 s 个记录,索引表和块内都用顺序查找)

⚠️ 当 s = √n 时 ASL 取最小值 √n + 1。

💡 评价:索引表占额外空间、索引查找有开销,但块内查找范围受限,总体效率仍显著优于普通顺序查找。

回源 · PDF 第 281 页 · b_281_4

7.3 树形查找

二叉排序树的定义和中序性质? ★4考

BST 或者是空树,或者满足: - 左子树非空 → 左子树所有结点的关键字均小于根 - 右子树非空 → 右子树所有结点的关键字均大于根 - 左右子树也分别是 BST

⚠️ 核心推论:对 BST 中序遍历可得到一个递增的有序关键字序列。

查找过程:与根比较 → 小于则进左子树,大于则进右子树 → 直到找到或树空。 ⚠️ 递归实现简单,但栈空间开销较大、执行效率较低,所以常用循环实现。

构造 BST 的目的:⚠️ 并非直接输出有序序列,而是利用有序结构支持高效的动态查找、插入和删除。

💡 判断整棵树是否为 BST 的两种稳妥方法: - 中序 + pre:中序遍历时要求当前关键字严格大于前一个(本书关键字互异约定) - 递归上下界:根必须落在 (lower, upper);进左子树把上界改为根值,进右子树把下界改为根值

⚠️ 校订/边界:只检查“左孩子 < 父 < 右孩子”不是充分条件。反例:根 10,左孩子 5,5 的右孩子 12;每条父子边都“看似正确”,但 12 落在 10 的左子树,整树不是 BST。若题目允许重复关键字,还要按题设改成非降并核对重复值放置规则。

★ 考过 2013、2015、2018、2024

回源 · PDF 第 291 页 · b_291_15;PDF 第 291 页 · b_291_17

BST 插入的新结点一定在哪? ★1考

⚠️ BST 是动态构建的:查找失败时才执行插入。 - 原树为空 → 新结点作根 - 否则从根比较,小于进左、大于进右 - ⚠️ 新插入的结点一定是叶结点,且恰好是查找失败时所访问的最后一个结点的左孩子或右孩子 - ⚠️ 树中已存在相同关键字则插入失败(返回 0)

构造 BST:从空树开始依次插入,重复关键字被忽略。 教材例:{45, 24, 53, 45, 12, 24} → 第二个 45 和 24 被忽略。

★ 考过 2020

回源 · PDF 第 292 页 · b_292_3

BST 删除的三种情况? ★1考

⚠️ 不能把以该结点为根的子树都删掉,必须摘下该结点并重新连接断裂的链,同时保持 BST 性质。 - ① z 是叶结点 → 直接删除 - ② z 只有一棵非空子树 → ⚠️ 把它唯一的子树上移,替代 z 的位置 - ③ z 有左右两棵子树 → ⚠️ 用 z 的直接后继或直接前驱(中序的下一个/上一个)替代 z,再删除那个后继(前驱) - ⚠️ 因为直接后继(前驱)至多只有一棵子树,这样就转化为情形 ① 或 ②

💡 思考题(教材原题):删除某结点再重新插入,所得 BST 未必与原树相同。

★ 考过 2013

回源 · PDF 第 293 页 · b_293_4

BST 的查找效率取决于什么?

⚠️ 主要取决于树的高度。 - 左右子树高度差不超过 1(平衡)→ ASL = O(log₂n) - ⚠️ 最坏情况:输入序列有序 → 退化为单支树,高度 n,ASL = (n+1)/2

教材算例(10 个结点): - 平衡形态 ASL_a = (1 + 2×2 + 3×4 + 4×3)/10 = 2.9 - 单支树 ASL_b = (1+2+…+10)/10 = 5.5

回源 · PDF 第 294 页 · b_294_4;PDF 第 294 页 · b_294_5

BST 和折半查找该怎么选?

  • ⚠️ 二分查找的判定树唯一;相同关键字集合可能生成不同的 BST(形态取决于插入顺序)
  • 平均时间性能二者相近
  • ⚠️ 维护有序性:BST 插入删除只需修改指针,O(log₂n);二分查找的对象是有序顺序表,插入删除要移动大量元素,O(n)

💡 结论:静态查找表 → 顺序表 + 二分查找;动态查找表(频繁增删)→ 二叉排序树。

回源 · PDF 第 294 页 · b_294_5

7.3.2 平衡二叉树

平衡因子的取值范围? ★1考

平衡因子 = 结点左子树高度 − 右子树高度。 ⚠️ 平衡二叉树(AVL 树)中所有结点的平衡因子只能取 −1、0 或 1。

形式化定义:空树,或左右子树均为平衡二叉树且左右子树高度差的绝对值不超过 1。

★ 考过 2009

回源 · PDF 第 294 页 · b_294_7;PDF 第 294 页 · b_294_9

什么是最小不平衡子树? ★1考

插入后沿查找路径向上检查各祖先结点是否失衡;⚠️ 找到插入路径上离新结点最近、且平衡因子绝对值大于 1 的结点 A —— 以 A 为根的子树即为最小不平衡子树。

⚠️ 每次调整的对象都是最小不平衡子树,且必须在保持 BST 特性的前提下旋转。

★ 考过 2015

回源 · PDF 第 294 页 · b_294_15

四种旋转分别怎么做? ★3考

类型 触发条件 平衡因子变化 操作
LL(右单旋转) 在 A 的左孩子的左子树上插入 1 → 2 B 向右上旋代替 A,A 向右下成为 B 的右孩子,B 的原右子树成为 A 的左子树
RR(左单旋转) 在 A 的右孩子的右子树上插入 −1 → −2 B 向左上旋代替 A,A 向左下成为 B 的左孩子,B 的原左子树成为 A 的右子树
LR(先左后右双旋转) 在 A 的左孩子的右子树上插入 1 → 2 先把 B 的右子树根 C 向左上旋取代 B,再把 C 向右上旋取代 A
RL(先右后左双旋转) 在 A 的右孩子的左子树上插入 −1 → −2 先把 B 的左子树根 C 向右上旋取代 B,再把 C 向左上旋取代 A

⚠️ LR 和 RL 旋转时,新结点插在 C 的左子树还是右子树不影响旋转过程。

💡 记忆法:看"失衡结点 → 孩子 → 孙子"的方向,同向单旋(反方向转一次),异向双旋(先把里面那个转出来)。

💡 3 + 4 重构:画树时统一 LL/RR/LR/RL - 沿失衡高链取 z(最小不平衡子树根)、y(z 的高孩子)、x(y 的高孩子) - 把三个关键字按 BST 顺序排成 a < b < c;把剩余四棵子树按中序顺序排成 T₁ < T₂ < T₃ < T₄ - 重挂为 b 作新根,a/c 作左右孩子;a 接 T₁/T₂,c 接 T₃/T₄ - 最后把 b 接回原 z 的父结点,并自下而上更新高度/平衡因子(若实现存 parent 指针也要同步)

⚠️ 边界:3 + 4 只是四种旋转的统一重挂法;x/y/z 必须来自失衡高链,四棵子树的中序次序不得改变。术语题仍要能识别 LL/RR/LR/RL。

★ 考过 2010、2019、2021

回源 · PDF 第 295 页 · b_295_2

构造 AVL 的教材例题(15,3,7,10,9,8)? ★1考

  • 插入 7 后失衡:最小不平衡子树根为 15,插入在其左孩子的右子树 → ⚠️ LR 旋转
  • 插入 9 后失衡:根为 15,插入在其左孩子的左子树 → ⚠️ LL 旋转
  • 插入 8 后失衡:根为 7,插入在其右孩子的左子树 → ⚠️ RL 旋转

💡 做题套路:先定位最小不平衡子树的根 A,再看新结点相对 A 走的是"左左/左右/右右/右左"。

★ 考过 2013

回源 · PDF 第 296 页 · b_296_8

AVL 删除和插入的调整有什么不同?

删除步骤: - ① 按 BST 方法删除结点 w - ② 从 w 向上回溯,找到第一个不平衡结点 z;设 y 是 z 的较高子树的根,x 是 y 的较高子树的根 - ③ 按 x、y、z 的相对位置分 LL / LR / RR / RL 四种情况调整(与插入相同)

⚠️ 删除的等高补丁:若 y 的两棵子树等高,x 不唯一,则优先选与 y 相对 z 同向的外侧孙子:z 左高就选 x=y.left,z 右高就选 x=y.right,优先归入 LL/RR 单旋。 ⚠️ 边界:这条是删除后“y 的两孩子等高”时的确定规则;插入路径通常已唯一确定 x,不要反向套用。

⚠️ 关键区别:插入只需对以 z 为根的子树做一次平衡调整;删除可能需要多次调整 —— 若一次调整使子树高度减 1,则可能还要继续调整 z 的祖先,甚至一路回溯到根。

教材例:删除 32(叶结点)→ 回溯找到第一个不平衡结点 44(z),y=78,x=50 → RL 情况 → 先右后左双旋。

回源 · PDF 第 297 页 · b_297_2;PDF 第 297 页 · b_297_8

高度为 h 的 AVL 树最少有多少结点? ★1考

递推式:nₕ = nₕ₋₂ + nₕ₋₁ + 1,其中 n₀ = 0、n₁ = 1、n₂ = 2。 依次推出:n₃ = 4、n₄ = 7、n₅ = 12、n₆ = 20、n₇ = 33 …

⚠️ 用途:求给定结点数的 AVL 树查找时的最多比较次数(树的最大深度)。 例:含 12 个结点的 AVL 树,因为 n₅ = 12,所以最多比较 5 次。

⚠️ 含 n 个结点的 AVL 树最大深度为 O(log₂n),平均查找时间复杂度 O(log₂n)。 💡 深度为 h 的 AVL 树最多结点数就是满二叉树的 2^h − 1。

★ 考过 2012

回源 · PDF 第 297 页 · b_297_10

7.3.3 红黑树

红黑树的五条性质?

  • ① 每个结点或红或黑
  • ② ⚠️ 根结点是黑色的
  • ③ ⚠️ 叶结点(虚构的外部 NULL 结点)都是黑色的
  • ④ ⚠️ 不存在两个相邻的红结点(红结点的父和孩子均为黑)
  • ⑤ ⚠️ 从任一结点到任意叶结点的简单路径上,所含黑结点的数量相同

黑高 bh = 从某结点出发(不含该结点)到叶结点路径上的黑结点总数;根的黑高称为红黑树的黑高。 ⚠️ 与折半查找树、B 树类似,引入 n + 1 个外部叶结点(视为黑色)以保证每个内部结点左右子树均非空。

💡 记忆法:"红不连红,黑高相同,根叶皆黑"。

回源 · PDF 第 298 页 · b_298_7

红黑树的两个高度结论?

  • 结论 1:⚠️ 从根到叶结点的最长路径不大于最短路径的 2 倍
  • 💡 推理:最短路径必然全由黑结点构成(性质⑤);最长路径必然由黑红交替构成(性质④),此时红结点数最多等于黑结点数
  • 结论 2:⚠️ 有 n 个内部结点的红黑树高度 h ≤ 2log₂(n+1)
  • 💡 推理:任意一条简单路径上至少一半是黑结点 → 根的黑高至少 h/2 → n ≥ 2^(h/2) − 1

⚠️ 推论:黑高为 h 的红黑树,内部结点数最少 2^h − 1,最多 2^(2h) − 1。

回源 · PDF 第 298 页 · b_298_17;PDF 第 298 页 · b_298_22

AVL 树和红黑树该怎么选?

  • AVL 是"高度平衡":左右子树高度差 ≤ 1,⚠️ 插入删除时要频繁调整全树拓扑,代价大
  • 红黑树是"适度平衡":⚠️ 允许左右子树高度相差最多 2 倍 → 显著降低调整频率

⚠️ 本书常用选型结论:查找远多于增删 → AVL 更优(查找更快);增删频繁 → 红黑树更合适(调整开销小)。 💡 教材常举的工程例:红黑树调整频率较低、综合表现均衡;C++ map/set 与 Java TreeMap/TreeSet 的常见实现采用红黑树。具体标准库是否规定内部结构不属于统考作答点。

回源 · PDF 第 299 页 · b_299_0

新插入的结点为什么染红?

⚠️ 若染黑:该结点所在路径的黑结点数比其他路径多 1,几乎必然违反性质⑤,且调整代价高。 ⚠️ 若染红:所有路径的黑结点数保持不变,仅当出现父子均为红时才违反性质④,局部调整即可高效恢复。

插入调整的三步: - ① 按 BST 规则插入 z 并染红;⚠️ 若父结点为黑,红黑性质未破坏,插入结束 - ② ⚠️ 若 z 为根,则染黑(满足性质②),树的黑高加 1 - ③ 若 z 非根且父结点为红 → 违反性质④;⚠️ 此时爷结点必然存在且为黑,按叔结点 y 的颜色分三种情形处理

💡 情形 1(LR 型):叔结点是黑色且 z 是父的右孩子 → 先对 z.p 左旋,使 z 上升取代原父位置,转化为情形 2;⚠️ 此操作不改变任何路径的黑结点数(z 与 z.p 均为红),性质⑤不受影响。

回源 · PDF 第 299 页 · b_299_1;PDF 第 299 页 · b_299_2

红黑树插入的三种情形怎么分?

⚠️ 按叔结点 y 的颜色分(以下设 z.p 是 z.p.p 的左孩子,右孩子情形对称): - 情形 1(LR 型,先左旋再右旋):叔结点 y 是黑色,且 z 是父的右孩子 - 先对 z.p 执行左旋,使 z 上升取代原父位置 → 转化为情形 2 - ⚠️ 此操作不改变任何路径的黑结点数(z 与 z.p 均为红),性质⑤不受影响 - 情形 2(LL 型,右单旋):叔结点 y 是黑色,且 z 是父的左孩子 - 对 z.p.p 执行右旋,⚠️ 并将原父结点染黑、原爷结点染红 → 插入结束 - 情形 3:⚠️ 叔结点 y 是红色(z 是左是右都不影响) - 把 z.p 和 y 染黑,把 z.p.p 染红 - ⚠️ z.p.p 变红后可能与其父再次红红冲突 → 把 z.p.p 视为新的 z 继续向上回溯,每次 z 上移两层 - 终止条件:z 成为根(染黑结束) 或 进入情形 1、2(旋转后结束)

💡 3 + 4 视角只用来画“黑叔 + 红红冲突”的旋转部分:把爷、父、z 按 BST 次序排成 a<b<c,四棵子树保持中序顺序重挂,再按王道规则着色,即可统一理解 LL/RR/LR/RL。 ⚠️ 边界:它不是红黑树完整修复算法。红叔必须换色并可能向上溢出,不能硬做 3 + 4;着色条件仍是考试作答主线。

⚠️ 补充陷阱:情形 3 回溯时 z 可能已上移到内部结点,从而拥有子树 —— 所有调整都必须考虑子树的存在。

回源 · PDF 第 299 页 · b_299_7

红黑树插入的教材算例(插 5、4、12)?

  • 插入 5:⚠️ 情形 3 —— 把父结点 3 与叔结点 10 染黑、爷结点 7 染红;7 是根 → 重新染黑,树的黑高加 1
  • 插入 4:⚠️ 情形 1 的对称情形(RL 型) —— 先对以 5 为根的子树右旋,转为情形 2 的对称(RR 型),交换 3 和 4 的颜色,再对以 4 为根的子树左旋
  • 插入 12:⚠️ 父结点为黑,无须调整,直接结束

💡 做题顺序:先看父是不是黑(是就结束)→ 再看叔的颜色(红走情形 3,黑走旋转)。

回源 · PDF 第 300 页 · b_300_6

红黑树删除为什么会出现"双黑结点"?

⚠️ 插入易破坏性质④(无连续红结点);删除更易破坏性质⑤ —— 被删结点为黑时,经过它的所有路径黑高减 1。

归约:有两个非空子树的结点不能直接删,用中序后继(右子树最小结点)替代 —— ⚠️ 该后继至多只有一个右孩子 → 最终只剩两种情形:有一个孩子、无孩子。 - 有一个孩子 → ⚠️ 该子树只有一个结点且必然是红色(否则破坏性质⑤) - 无孩子且是红色 → 直接删,无须调整 - 无孩子且是黑色 → ⚠️ 把替换它的结点 x 视为带"额外一重黑色"的双黑结点,任务转化为把双黑结点恢复为普通结点

回源 · PDF 第 301 页 · b_301_10;PDF 第 301 页 · b_301_14

红黑树删除的四种情形?(了解即可)

⚠️ 教材原话:本节难度较大、考查概率较低,可按自身情况决定是否学习。

按 x 的兄弟 w 及 w 的孩子颜色分(设 x 是左孩子,右孩子对称): - 情形 1:w 是红色 → 交换 w 与父结点颜色,对 x.p 左旋 → ⚠️ 转为情形 2、3 或 4 - 情形 2(RR 型,左单旋):w 黑,w 的右孩子红 → 交换 w 与 x.p 颜色,把 w 的右孩子染黑,对 x.p 左旋 → x 变单重黑,结束 - 情形 3(RL 型,先右旋再左旋):w 黑,w 的左孩子红、右孩子黑 → 交换 w 与其左孩子颜色,对 w 右旋 → 转为情形 2 - 情形 4:w 黑,w 的两个孩子都黑 → ⚠️ 从 x 和 w 各去掉一重黑色(x 变普通黑、w 变红),把 x.p 额外着一层黑 → x 上升一层继续循环

💡 红侄删除的 3 + 4 视角:兄弟 w 为黑且至少有一个红侄子时,可把“父、兄弟、选定的红侄”作为三结点重挂;若内外侄都红,优先取外侧侄子,可直接归入单旋情形。 ⚠️ 边界:若兄弟及两侄均黑,必须执行情形 4 的双黑上传,3 + 4 无法替代;所有旋转后仍必须按原情形完成着色。

⚠️ 只有情形 4 可能重复执行,每次 x 上升一层,至多 O(log₂n) 次;情形 1、2、3 各执行常数次着色和至多 3 次旋转后即终止。 ⚠️ 若由情形 1 进入情形 4,因原 x.p 是红色,把新 x 变黑即终止。

回源 · PDF 第 302 页 · b_302_4;PDF 第 302 页 · b_302_5

7.4 B 树和 B+ 树

m 阶 B 树的五条定义? ★2考

  • ⚠️ 每个结点至多 m 棵子树,即至多 m − 1 个关键字
  • ⚠️ 根结点若不是叶结点,则至少 2 棵子树,即至少 1 个关键字
  • ⚠️ 除根外,所有非叶结点至少 ⌈m/2⌉ 棵子树,即至少 ⌈m/2⌉ − 1 个关键字
  • 结点结构:n | P₀ | K₁ | P₁ | K₂ | … | Kₙ | Pₙ —— K₁ < K₂ < … < Kₙ,Pᵢ₋₁ 所指子树全小于 Kᵢ,Pᵢ 所指子树全大于 Kᵢ
  • ⚠️ 所有叶结点都在同一层,且不实际存储数据(可视为查找失败的外部结点,作用类似折半查找判定树中的失败结点)

⚠️ 术语分歧(务必注意):多数教材把 B 树的叶结点定义为失败结点,本书采用此定义;但统考真题把 B 树的叶结点定义为最底层终端结点。

★ 考过 2009、2025

回源 · PDF 第 317 页 · b_317_3

B 树关键字数与子树数的关系?(5 阶实例) ★4考

  • ⚠️ 任意结点的子树个数 = 其关键字个数 + 1
  • 根至少 1 个关键字 → 至少 2 棵子树
  • 5 阶时:除根外非叶结点至少 ⌈5/2⌉ = 3 棵子树(至少 2 个关键字),至多 5 棵子树(至多 4 个关键字)
  • 结点内关键字从左到右严格递增;⚠️ 下层子树的关键字落在上层关键字划分出的区间内(如关键字 5、11 划出 (−∞,5)、(5,11)、(11,+∞))

★ 考过 2013、2014、2018、2021

回源 · PDF 第 317 页 · b_317_9

B 树查找为什么要分两步?

  • ① 在 B 树中定位目标结点 —— ⚠️ 这一步在磁盘上进行
  • ② 在结点内查找关键字 —— ⚠️ 这一步在内存中进行(结点读入内存后用顺序或折半查找)

⚠️ 所以磁盘上的查找次数(结点所在层次数)才是决定查找效率的关键因素。

查找失败的标志:⚠️ 查找到叶结点(外部结点)说明树中不存在该关键字。

回源 · PDF 第 318 页 · b_318_1

B 树高度的上下界怎么推?

(⚠️ 本书的高度不包括最底层外部叶结点那一层) - 最小高度(每结点关键字数最大): n ≤ (m−1)(1 + m + m² + … + m^(h−1)) = m^h − 1 → ⚠️ h ≥ log_m(n+1) - 最大高度(每结点关键字数最小): 第 1 层 ≥1 个结点,第 2 层 ≥2,第 3 层 ≥2⌈m/2⌉ …,第 h+1 层 ≥2(⌈m/2⌉)^(h−1) ⚠️ 外部叶结点数恒为 n + 1 → n + 1 ≥ 2(⌈m/2⌉)^(h−1) → ⚠️ h ≤ log_⌈m/2⌉((n+1)/2) + 1

教材算例:3 阶 B 树含 8 个关键字 → 2 ≤ h ≤ 3.17 → 实际 2 ≤ h ≤ 3。

回源 · PDF 第 318 页 · b_318_3;PDF 第 318 页 · b_318_5

B 树插入的定位与分裂规则? ★1考

  • ① 定位:⚠️ 查找必然落到外部叶结点(查找失败),但实际插入位置是它的父结点,即最底层终端结点
  • ② 插入与分裂:⚠️ 每个非根结点的关键字数必须在 [⌈m/2⌉−1, m−1] 内
  • 插入后 ≤ m−1 → 直接插入
  • 插入后 = m → 必须分裂

分裂方法:⚠️ 从第 ⌈m/2⌉ 个关键字处分成左右两部分 —— 左半留原结点,右半移入新结点,⚠️ 中间那个关键字(是关键字不是结点)被提升插入父结点;父结点若也超限则递归分裂,⚠️ 一直传到根被分裂时 B 树高度加 1。

教材例(m=3):结点已有 2 个关键字,插入 60 后有 3 个 → 分裂,中间关键字 52 上提,原结点与新结点各留 1 个。

★ 考过 2020

回源 · PDF 第 318 页 · b_318_11

B 树删除的三种情况? ★2考

⚠️ 被删关键字不在终端结点时:用其前驱(左子树最右下)或后继(右子树最左下)k′ 替代,再去删 k′ —— k′ 必在终端结点,转化为下面三种情况。 教材例:4 阶 B 树删 80,用前驱 78 替代,再在终端结点删 78。

  • ① 直接删除:删除前该结点关键字数 ≥ ⌈m/2⌉ → 直接删
  • ② 兄弟够借:该结点关键字数 = ⌈m/2⌉−1,且相邻兄弟 ≥ ⌈m/2⌉ → ⚠️ 父子换位法
  • 教材例:删 65 → 把父结点的 71 下移替代 65,再把右兄弟的最小关键字 74 上移到父结点原 71 的位置
  • ③ 兄弟不够借:该结点和左右兄弟都是 ⌈m/2⌉−1 → ⚠️ 把该结点、一个兄弟、父结点中分隔它们的关键字合并为一个新结点

★ 考过 2012、2022

回源 · PDF 第 319 页 · b_319_5

合并后父结点关键字减少会怎样? ★1考

⚠️ 合并过程中父结点的关键字个数会减 1: - 若父是根且关键字数减到 0 → ⚠️ 直接删除根结点,合并后的新结点成为根(树高减 1) - 若父不是根且关键字数减到 ⌈m/2⌉−2 → ⚠️ 对父结点执行借位或合并,并可能向上递归,直到整棵树重新满足 B 树性质

★ 考过 2023

回源 · PDF 第 320 页 · b_320_1

B+ 树的五条定义? ★1考

  • 每个分支结点最多 m 棵子树
  • 非叶根结点至少 2 棵子树;其余分支结点至少 ⌈m/2⌉ 棵子树
  • ⚠️ 每个分支结点的关键字个数 = 其子树个数(B 树是子树数 = 关键字数 + 1)
  • ⚠️ 所有关键字及其记录指针都存储在叶结点中;叶结点内关键字升序排列,⚠️ 相邻叶结点用指针按关键字顺序链接,支持高效顺序查找
  • ⚠️ 分支结点(索引的索引)只含引导查找的关键字(通常是子结点关键字的最大值)和指针

★ 考过 2017

回源 · PDF 第 320 页 · b_320_5

B 树和 B+ 树的四点差异? ★1考

B 树 B+ 树
子树数 n 个关键字 → n+1 棵子树 ⚠️ n 个关键字 → n 棵子树
关键字数范围 ⌈m/2⌉−1 ≤ n ≤ m−1(根 1 ≤ n ≤ m−1) ⚠️ ⌈m/2⌉ ≤ n ≤ m(非叶根 2 ≤ n ≤ m)
关键字存储 ⚠️ 只出现一次,各结点关键字互不重复 ⚠️ 全部存在叶结点,非叶结点中的是副本(最大值),会重复出现
结点功能 各结点都存数据 ⚠️ 叶结点存完整数据,非叶结点仅起索引作用

💡 B+ 树为什么适合数据库:非叶结点结构更紧凑 → 一个磁盘块能容纳更多关键字 → 减少磁盘 I/O 次数;⚠️ 叶结点链表还支持范围查询。

★ 考过 2016

回源 · PDF 第 320 页 · b_320_13

B+ 树的两个头指针和两种查找方式?

⚠️ B+ 树通常有两个头指针:一个指向根结点,另一个指向关键字最小的叶结点。 → 支持两种查找:从最小关键字开始的顺序查找、从根结点开始的多路查找。

⚠️ 查找过程的关键差异:即使在非叶结点遇到与给定关键字相等的值也不终止,必须继续向下走到叶结点 → 无论成功与否,每次查找都对应一条从根到某叶结点的完整路径。

💡 这也是 B+ 树查找长度稳定的原因(B 树可能在中途命中提前结束)。

回源 · PDF 第 320 页 · b_320_19

7.5 散列表

冲突和同义词是什么?

散列函数:H(key) = Addr,把关键字映射到存储地址(数组下标、索引或内存地址)。 - ⚠️ 冲突:两个或以上不同关键字映射到同一地址 - ⚠️ 同义词:这些发生冲突的不同关键字

⚠️ 冲突总是不可避免的 → 一方面设计好的散列函数减少冲突,另一方面必须设计有效的冲突处理方法。 💡 理想情况下散列表查找的时间复杂度为 O(1),与表中元素个数无关。

回源 · PDF 第 329 页 · b_329_12

构造散列函数的三点要求?

  • ⚠️ 定义域必须包含全部关键字,值域范围取决于散列表大小
  • 计算出的地址应尽可能均匀分布在整个地址空间
  • 函数应尽量简单,能在较短时间内算出
回源 · PDF 第 330 页 · b_330_3;PDF 第 330 页 · b_330_18

四种散列函数的适用场景?

  • 直接定址法:H(key) = key 或 a·key + b —— ⚠️ 计算最简单且不会产生冲突;适用于关键字分布基本连续,⚠️ 分布稀疏时浪费空间
  • 除留余数法(⚠️ 最简单最常用):H(key) = key % p,⚠️ p 取不超过 m 且尽可能接近 m 的质数
  • 数字分析法:⚠️ 选取数码分布较均匀的数位组合成地址;适用于关键字集合已知且固定,⚠️ 集合变化就要重构函数
  • 平方取中法:取关键字平方值的中间几位;⚠️ 平方运算与关键字每一位都有关,地址分布较均匀;适用于各位取值分布不均或位数较少的情形

⚠️ 不能笼统地说某种方法最优,要根据关键字集合的特性选择。

回源 · PDF 第 330 页 · b_330_6

开放定址法的通式和四种增量? ★1考

\[H_i = (H(\text{key}) + d_i) \% m\]

⚠️ 开放定址法 = 散列表中所有空闲地址都可用于存放任意关键字(无论是否同义)。

  • 线性探测法:dᵢ = 1, 2, …, m−1 —— 探测到表尾就回绕到表首;⚠️ 只要表未满必能找到空位
  • 平方探测法(二次探测法):dᵢ = 1², −1², 2², −2², …, k², −k²(k ≤ m/2);⚠️ 散列表长度 m 必须是形如 4k+3 的素数
  • 双散列法:dᵢ = i·H₂(key) → Hᵢ = (H(key) + i·H₂(key)) % m,⚠️ 需要两个散列函数
  • 伪随机序列法:dᵢ 由伪随机数生成器产生

★ 考过 2025

回源 · PDF 第 331 页 · b_331_5;PDF 第 331 页 · b_331_9

什么是堆积(聚集)现象? ★1考

⚠️ 线性探测法的固有缺陷:原本映射到地址 i 的同义词被存入 i+1,本应存入 i+1 的元素被迫占用 i+2,以此类推 → 大量元素在相邻地址上堆积,显著降低查找效率。

⚠️ 平方探测法能有效避免堆积,是一种较好的冲突处理方法;⚠️ 缺点是无法探测散列表中的所有位置,但至少能覆盖一半的地址空间。

★ 考过 2014

回源 · PDF 第 331 页 · b_331_6

开放定址法为什么不能直接删除元素? ★1考

⚠️ 直接物理删除可能截断其他同义词的查找路径,导致查找失败。

正确做法:对被删元素所在位置设置一个删除标记,实现逻辑删除。 ⚠️ 副作用:经过多次删除后,散列表看似已满,但实际上有许多位置未被利用。

★ 考过 2023

回源 · PDF 第 331 页 · b_331_15

拉链法的组织方式和适用场景?

⚠️ 把散列到同一地址的所有同义词组织成一个链表 —— 散列地址为 i 的同义词链表,其头指针存放在散列表的第 i 个单元中。

⚠️ 拉链法特别适用于需要频繁执行插入和删除操作的场景(不存在开放定址法的删除难题)。

教材例:{19, 14, 23, 01, 68, 20, 84, 27, 55, 11, 10, 79},H(key) = key % 13。

回源 · PDF 第 331 页 · b_331_18;PDF 第 331 页 · b_331_19

散列查找的两个步骤? ★4考

初始化 Addr = H(key): - ① 检查 Addr 处是否有记录:无记录 → 查找失败;有记录则比较,相等 → 成功,否则转 ② - ② 按冲突处理方法计算下一个探测地址,更新 Addr,返回 ①

教材算例(线性探测,表长 16,H(key) = key % 13): - 查 84:H(84)=6,L[6]≠84 → H₁=(6+1)%16=7,L[7]≠84 → H₂=8,L[8]=84 成功 - 查 38:H(38)=12,L[12]≠38 → H₁=13,L[13] 为空 → 查找失败

⚠️ 注意查找失败的判据是"探测到空单元",不是"探测完整张表"。

★ 考过 2010、2018、2019、2024

回源 · PDF 第 332 页 · b_332_0

散列表 ASL 怎么算?(教材算例)

教材例各关键字的比较次数:14→1, 01→2, 68→1, 27→4, 55→3, 19→1, 20→1, 84→3, 79→9, 23→1, 11→1, 10→3

\[\mathrm{ASL} = (1\times6 + 2 + 3\times3 + 4 + 9)/12 = 2.5\]

⚠️ 重要结论:对同一关键字集合和相同散列函数,不同的冲突处理方法会生成不同的散列表,从而 ASL 不同(本例线性探测的结果就与拉链法不同)。 ⚠️ 尽管散列表建立了直接映射,但由于冲突的存在,查找仍需比较 → ASL 仍是衡量效率的核心指标。

回源 · PDF 第 332 页 · b_332_14;PDF 第 332 页 · b_332_16

影响散列表查找效率的三个因素? ★2考

  • 散列函数
  • 冲突处理方法
  • 装填因子 α
\[\alpha = \frac{\text{表中记录数} n}{\text{散列表长度 } m}\]

⚠️ ASL 主要依赖于装填因子 α,而不直接依赖于 n 或 m。 α 越大表越满、冲突可能性越高;α 越小冲突越少。

★ 考过 2011、2022

回源 · PDF 第 332 页 · b_332_19

【原书试题精选与答案方法】第7章

有序表和无序表做顺序查找时,三种情况下的 ASL 为什么不总相同?(7.2 综合应用题 01)

分“失败、唯一命中、多重命中”讨论:

  • 查找失败:有序表遇到第一个大于目标值的元素即可停止;无序表必须扫到表尾,二者不同。
  • 唯一命中:命中第 \(i\) 个位置都比较 \(i\) 次,等概率时二者相同。
  • 找出全部相等元素:有序表的相同值连续,找到第一个后可连续收集;无序表仍须扫描全表,二者不同。

⚠️ “表有序”并不会自动降低成功查找的 ASL;只有它能提供提前失败或连续收集重复值时才体现优势。

回源 · PDF 第 288 页 · b_288_4;PDF 第 288 页 · b_288_5;PDF 第 288 页 · b_288_6;PDF 第 288 页 · b_288_7

折半查找判定树怎样同时解决查找路径、成功/失败 ASL 和最多比较次数?(7.2 综合应用题 02;2010、2023 统考真题)

先按题目固定的 mid 取整规则递归取中点,画出圆形成功结点;再在每个空子树位置补一个方形失败结点。

  • Q02:查 275 依次比较 509、154、275;查 684 依次比较 509、677、897、765。
  • 成功 ASL 按圆形结点层次加权:本题为 \(45/14\)。
  • 失败 ASL 按失败区间等概率加权,但比较只算到方形结点的父结点:本题为 \(59/15\)。
  • 最多比较次数等于判定树高度,长度 16 时为 5,长度 600 时为 10。

⚠️ 方形失败结点是虚构结点,本身不增加关键字比较次数。

回源 · PDF 第 287 页 · b_287_3;PDF 第 287 页 · b_287_4;PDF 第 287 页 · b_287_5;PDF 第 287 页 · b_287_15;PDF 第 287 页 · b_287_16;PDF 第 288 页 · b_288_8;PDF 第 288 页 · b_288_11;PDF 第 288 页 · b_288_12;PDF 第 288 页 · b_288_14;PDF 第 288 页 · b_288_15

“先每隔 8 个顺序定位,再在块内折半”怎样计算 ASL?(7.2 综合应用题 03)

这是一个固定块长为 8 的两级查找:先比较 \(A[7],A[15],\dots\) 确定块;若目标不等于已比较过的块尾元素,再在该块前面的 7 个元素中折半。

  • 第 \(i\) 块要先做 \(i\) 次索引顺序比较。
  • 每块 8 个目标位置中,块尾元素已在第一阶段命中,不再做块内比较;其余 7 个位置的折半比较次数总和为 \(1+2\times2+3\times4=17\),所以平均附加量是 \(17/8\)。
  • 等概率下教材化简为
\[ \mathrm{ASL}_{\text{成功}}=\frac{n+1}{2}+\frac{17}{8}. \]

💡 两级查找一律按“定位块的代价 + 块内查找的代价”计算,不能只算其中一级。

回源 · PDF 第 288 页 · b_288_16;PDF 第 288 页 · b_288_17;PDF 第 288 页 · b_288_18;PDF 第 289 页 · b_289_0

折半查找的递归写法怎样处理成功、失败和递归栈?(7.2 综合应用题 04)

递归区间为 [low,high]:

  • low>high:查找失败,按题目约定返回 0。
  • key>elem[mid]:递归右半 [mid+1,high]。
  • key<elem[mid]:递归左半 [low,mid-1]。
  • 相等:返回 mid。

每次规模减半,时间 \(O(\log n)\);递归工作栈深度同为 \(O(\log n)\)。若改成循环写法,额外空间可降为 \(O(1)\)。

回源 · PDF 第 289 页 · b_289_1;PDF 第 289 页 · b_289_2;PDF 第 289 页 · b_289_3;PDF 第 289 页 · b_289_4;PDF 第 289 页 · b_289_5

为什么折半查找的 O(logn) 不代表每一次都比顺序查找比较少?(7.2 普通选择题 06)

复杂度描述的是规模增大后的总体增长趋势,不能替代某一次具体查找的比较次数。

  • 例如在 1000 个元素的有序表中查第一个元素,顺序查找只比较 1 次,折半查找却要先从中部不断缩小区间,比较次数接近 \(\log_2 1000\)。
  • 因此只能说折半查找在一般情况或大部分位置更快,不能说对每个目标都必然更快。
  • 若各元素查找概率不等,还要按概率加权比较 ASL,不能只比较两种算法的渐近量级。
回源 · PDF 第 285 页 · b_285_9;PDF 第 285 页 · b_285_10

不等概率顺序查找怎样通过“与前驱交换”逐渐自组织?(7.2 综合应用题 05)

从表头顺序扫描;若找到目标且它不是首元,就与直接前驱交换,使高频结点逐步向表头移动。

  • 顺序表:交换相邻两个记录并返回新下标。
  • 链表:必须保存目标、前驱及前驱的前驱,改链前先保留旧链接。
  • 单次查找最坏 \(O(n)\),额外空间 \(O(1)\)。

⚠️ 这是“每命中一次只前移一位”,不是一次性按频度整体排序。

回源 · PDF 第 289 页 · b_289_6;PDF 第 289 页 · b_289_7;PDF 第 289 页 · b_289_8;PDF 第 289 页 · b_289_9;PDF 第 290 页 · b_290_0

行列都递增的矩阵怎样在 O(n) 时间内查找目标值?(7.2 综合应用题 06)

从右上角开始:当前值大于目标就左移一列;小于目标就下移一行;相等则成功。每一步都能排除一整行或一整列。

  • 最多左移 \(n-1\) 次、下移 \(n-1\) 次,比较不超过 \(2n\) 次。
  • 时间 \(O(n)\),空间 \(O(1)\)。

💡 右上角同时具有“向左变小、向下变大”两种单调方向;左下角也可对称处理。

回源 · PDF 第 290 页 · b_290_1;PDF 第 290 页 · b_290_2;PDF 第 290 页 · b_290_3;PDF 第 290 页 · b_290_4;PDF 第 290 页 · b_290_5;PDF 第 290 页 · b_290_6

查找概率不等时,为什么顺序查找或 BST 可能优于折半查找?(2013 统考真题)

折半查找优化的是均匀概率下的树高,概率不等时应让高概率元素获得更短路径。

  • 顺序存储:按概率降序排成 do, while, for, repeat(同概率者次序可互换),顺序查找 ASL 为 \(2.1\)。
  • 链式存储:同样按概率降序做单链表,顺序查找 ASL 仍为 \(2.1\)。
  • 也可用二叉链表构造概率友好的 BST,教材给出的 ASL 为 \(2.0\)。

⚠️ 折半查找的前提是按关键字有序;不能为照顾概率任意重排后仍声称使用折半查找。

回源 · PDF 第 290 页 · b_290_7;PDF 第 290 页 · b_290_8;PDF 第 290 页 · b_290_9;PDF 第 290 页 · b_290_10;PDF 第 290 页 · b_290_12

怎样判断一串关键字能否成为折半查找的比较序列?(2015 统考真题)

把每次比较后的可行区间同步收窄:目标小于当前关键字就更新上界,大于则更新下界;后续关键字必须始终落在当前区间内。

另一种等价方法是画出路径,检查它能否嵌入一棵二叉排序树。教材选项 A 在路径约束上发生矛盾,因此不能构成比较序列。

💡 通法不是只看相邻两数,而是维护“截至当前仍可能出现的上下界”。

回源 · PDF 第 287 页 · b_287_7;PDF 第 287 页 · b_287_8;PDF 第 287 页 · b_287_9;PDF 第 287 页 · b_287_10

跳跃式顺序查找中,目标越靠前为什么比较越少?(2016 统考真题)

题中伪代码按固定步长跳着扫描升序数组,本质仍是顺序排除候选位置;目标越早落入前面的探查点或区间,完成的比较轮次越少。

⚠️ 不要因为代码里有“跳跃”就自动套 \(O(\log n)\)。只有每轮把候选规模按比例缩小,才具有对数级特征;固定步长通常仍是线性级。

回源 · PDF 第 287 页 · b_287_11;PDF 第 287 页 · b_287_12

一棵树能否作为折半查找判定树,为什么还要检查 mid 取整方向?(2017 统考真题)

折半查找判定树不仅是平衡 BST,还受同一套 mid 取整规则约束。

  • 若始终向下取整,偶数个元素时左子树比右子树少 1 个或二者相等。
  • 若始终向上取整,偶数个元素时左子树比右子树多 1 个或二者相等。
  • 一棵候选树若某处体现向上取整、另一处又体现向下取整,就不可能由同一算法生成。
回源 · PDF 第 287 页 · b_287_13;PDF 第 287 页 · b_287_14

哪些结构不适合直接折半查找?(2024 统考真题)

折半查找要求同时满足:有序,且能按下标 \(O(1)\) 随机定位中点。

  • 数组或顺序表适合。
  • 链表、静态链表即使有序,也需沿链寻找中点;反复定位会失去折半优势,因此不适合直接使用。

⚠️ “逻辑上有序”只是一个条件,“物理上支持随机存取”同样不可少。

回源 · PDF 第 287 页 · b_287_17;PDF 第 287 页 · b_287_18;PDF 第 288 页 · b_288_0

顺序索引、块内也顺序查找时,最优块长为什么是 √n?(2025 统考真题)

设每块含 \(s\) 个元素,块数 \(k=n/s\)。等概率时

\[ \mathrm{ASL}=\frac{k+1}{2}+\frac{s+1}{2} =\frac{n/s+s}{2}+1. \]

由均值不等式,\(n/s=s\) 时最小,所以 \(s=\sqrt n\)。本题 \(n=400\),最优块长为 20。

⚠️ 该结论依赖“索引顺序查找 + 块内顺序查找 + 均匀分块”。若两级使用折半查找,结论要重新推导。

回源 · PDF 第 288 页 · b_288_1;PDF 第 288 页 · b_288_2

已知 BST 的先序或插入序列,怎样还原树并计算 ASL?(7.3 综合应用题 01、02)

  • 先序序列还原:首元素是根;利用 BST 的中序序列必为递增序列,先序 + 中序可唯一重建。
  • 插入序列建树:从空树开始逐个比较并落到空孩子位置。
  • 成功 ASL:按真实结点层次加权;失败 ASL:补全空孩子对应的失败区间,比较次数算到其父结点。

教材 Q01 得成功 ASL \(2.9\)、失败 ASL \(39/11\);Q02 成功 ASL \(3.2\)。

回源 · PDF 第 313 页 · b_313_3;PDF 第 313 页 · b_313_5;PDF 第 313 页 · b_313_6;PDF 第 313 页 · b_313_7;PDF 第 313 页 · b_313_8;PDF 第 313 页 · b_313_9;PDF 第 313 页 · b_313_10;PDF 第 313 页 · b_313_11;PDF 第 313 页 · b_313_13

n 个不同关键字能构造多少种 BST 形态,为什么会出现 Catalan 数?(7.3 普通选择题 09)

不同关键字的升序序列固定了 BST 的中序序列;每一种树形再配合其先序序列,就能唯一确定一棵 BST。因此,BST 形态数等于 n 个结点的二叉树形态数:

\[ C_n=\frac{1}{n+1}\binom{2n}{n}. \]

本题 \(n=5\),所以 \(C_5=42\)。

⚠️ 题目问的是不同树形,不是插入序列数;多个不同插入序列可能生成同一棵 BST。

回源 · PDF 第 308 页 · b_308_2;PDF 第 308 页 · b_308_3

AVL 插入手算怎样统一处理 LL、RR、LR、RL?(7.3 综合应用题 03;2010、2013、2021 统考真题)

从新结点向根回溯,找到第一个平衡因子绝对值变为 2 的结点 z,再看插入路径的两步方向:

  • LL:对 z 右旋;RR:对 z 左旋。
  • LR:先对左孩子左旋,再对 z 右旋。
  • RL:先对右孩子右旋,再对 z 左旋。

教材综合题依次出现 LL、RR、RL、RL;2010 插入 48 后为 RL,调整后 37 的孩子是 24、53;2013 顺序插入 1~7 后平衡因子为 0 的分支结点有 3 个;2021 插入 23 后 RL 调整,根为 25。

⚠️ 旋转后仍要保持 BST 的中序次序不变。

回源 · PDF 第 310 页 · b_310_3;PDF 第 310 页 · b_310_4;PDF 第 310 页 · b_310_6;PDF 第 311 页 · b_311_4;PDF 第 311 页 · b_311_5;PDF 第 312 页 · b_312_9;PDF 第 312 页 · b_312_10;PDF 第 313 页 · b_313_14;PDF 第 313 页 · b_313_16;PDF 第 313 页 · b_313_18;PDF 第 314 页 · b_314_1;PDF 第 314 页 · b_314_3

固定高度的 AVL 有多少种树形,怎样按左右子树高度递推?(7.3 普通选择题 13)

设 \(A_h\) 为高度恰为 h 的 AVL 树形数。根的左右子树高度只能是 \((h-1,h-1)\)、\((h-1,h-2)\)、\((h-2,h-1)\),因此

\[ A_h=A_{h-1}^2+2A_{h-1}A_{h-2}. \]

按题目层高口径,\(A_1=1\)、\(A_2=3\),所以

\[ A_3=3\times3+3\times1+1\times3=15. \]

💡 先枚举允许的“左右高度对”,再乘法组合左右子树形态;不要把 AVL 误当完全二叉树只画一种。

回源 · PDF 第 308 页 · b_308_7;PDF 第 308 页 · b_308_8;PDF 第 308 页 · b_308_11;PDF 第 308 页 · b_308_12;PDF 第 308 页 · b_308_13

关键字递增插入 AVL 时,怎样利用满树边界判断何时增高?(7.3 普通选择题 15)

按题目“单根高度为 0”的口径,递增插入到 \(2^{h+1}-1\) 个关键字时,教材给出的 AVL 恰为高度 h 的满树;再插入 1 个关键字,树高增为 \(h+1\)。

本题先插入 1~1023:\(1023=2^{10}-1\),树高为 9;再插入 1024,树高变为 10。

⚠️ 先确认高度是“边数”还是“层数”。同一棵树若按层数计高,数值会多 1。

回源 · PDF 第 308 页 · b_308_16;PDF 第 308 页 · b_308_17

等概率关键字的“最佳 BST”怎样构造?(7.3 综合应用题 04)

先将关键字升序排列,再仿照折半查找判定树:尽量取中间关键字为根,使左右子树结点数接近,从而让树高和等概率 ASL 尽量小。

⚠️ 这是等概率下的教材构造法;若概率不同,应按加权路径长度优化,不能只追求完全平衡。

回源 · PDF 第 314 页 · b_314_4;PDF 第 314 页 · b_314_5;PDF 第 314 页 · b_314_6

怎样用一次中序遍历判断二叉树是否为 BST?(7.3 综合应用题 05)

BST 的中序序列应严格递增。递归中序遍历时用 predt 保存前一个访问值:若发现 predt>=current->data,立即判否;否则更新 predt 并继续右子树。

  • 时间 \(O(n)\)。
  • 递归栈空间 \(O(h)\)。
  • ⚠️ 初值应是真正的负无穷或额外的“尚无前驱”标志,不能让某个普通常量误伤合法关键字。
回源 · PDF 第 314 页 · b_314_7;PDF 第 314 页 · b_314_8;PDF 第 314 页 · b_314_9;PDF 第 314 页 · b_314_10

怎样求指定结点在 BST 中的层次?(7.3 综合应用题 06)

沿 BST 查找路径向下:每与一个结点比较并下降一层,层次计数加 1;找到目标时返回计数。

  • 平均时间取决于树高,随机 BST 通常为 \(O(\log n)\);最坏退化链时为 \(O(n)\)。
  • 若树中可能有重复关键字,只比较 data 未必能唯一定位“指定结点”,应按题设约定处理。
回源 · PDF 第 314 页 · b_314_11;PDF 第 314 页 · b_314_12;PDF 第 314 页 · b_314_13;PDF 第 315 页 · b_315_0

选择题中怎样快速判断一棵树是否满足 AVL 定义?(2009 统考真题)

从叶结点向上标出每个非叶结点的左右子树高度,计算平衡因子;任一结点的绝对值超过 1 即排除。2009 题只有选项 B 的所有结点都满足该条件。

⚠️ 不能只检查根结点;AVL 要求任意结点都平衡。

回源 · PDF 第 310 页 · b_310_1;PDF 第 310 页 · b_310_2

怎样在一次后序遍历中判断整棵二叉树是否为 AVL?(7.3 综合应用题 07)

后序递归让每棵子树同时返回“高度 h”和“是否平衡 balance”:

  • 空树返回高度 0、平衡真。
  • 当前高度为 max(hl,hr)+1。
  • 只有左右子树都平衡且 \(|h_l-h_r|<2\),当前树才平衡。

时间 \(O(n)\)、递归栈 \(O(h)\)。

回源 · PDF 第 315 页 · b_315_1;PDF 第 315 页 · b_315_2;PDF 第 315 页 · b_315_3;PDF 第 315 页 · b_315_5

BST 的最小、最大关键字为什么不需要逐个比较?(7.3 综合应用题 08)

由 BST 性质,最小关键字在最左下结点,最大关键字在最右下结点。分别沿 lchild 或 rchild 走到空即可。

时间 \(O(h)\)、空间 \(O(1)\);最值结点不一定是叶结点,但最小结点必无左孩子,最大结点必无右孩子。

回源 · PDF 第 315 页 · b_315_6;PDF 第 315 页 · b_315_7;PDF 第 315 页 · b_315_8

怎样从大到小输出 BST 中所有不小于 k 的关键字?(7.3 综合应用题 09)

采用逆中序“右—根—左”,并利用阈值剪枝:

  • 先访问右子树。
  • 仅当当前值 \(\ge k\) 时输出;若当前值小于 k,其左子树更小,可整棵剪掉。
  • 再访问仍可能含合格值的左子树。

教材给出逆中序主线;实现时补上阈值判断和剪枝,避免把所有结点无条件输出。

回源 · PDF 第 316 页 · b_316_0;PDF 第 316 页 · b_316_1;PDF 第 316 页 · b_316_2;PDF 第 316 页 · b_316_3

带子树结点数 count 的 BST 怎样在平均 O(logn) 内找第 k 小?(7.3 综合应用题 10)

设左子树大小为 \(L\):

  • \(k=L+1\):当前结点就是第 k 小。
  • \(k\le L\):递归左子树,k 不变。
  • \(k>L+1\):递归右子树,改查第 \(k-L-1\) 小。

先检查 \(1\le k\le t->count\)。时间等于一条根到结点路径,随机 BST 平均 \(O(\log n)\);若树退化则最坏 \(O(n)\)。

回源 · PDF 第 316 页 · b_316_4;PDF 第 316 页 · b_316_5;PDF 第 316 页 · b_316_6;PDF 第 316 页 · b_316_7;PDF 第 316 页 · b_316_8;PDF 第 316 页 · b_316_10;PDF 第 316 页 · b_316_11

BST 查找路径和插入序列题怎样用“动态上下界”排除?(2011、2020 统考真题)

沿某条 BST 查找路径时维护合法区间 (low,high):向左后更新 high=current,向右后更新 low=current;后续关键字必须始终落在区间内。

判断一个输入序列能否生成指定 BST 时也一样:逐个按 BST 插入规则模拟;只要某元素落点与目标树不符即可排除。

⚠️ 只检查“左小右大”的相邻关系不够,必须服从所有祖先共同限定的区间。

回源 · PDF 第 310 页 · b_310_7;PDF 第 310 页 · b_310_8;PDF 第 310 页 · b_310_9;PDF 第 312 页 · b_312_6;PDF 第 312 页 · b_312_7;PDF 第 312 页 · b_312_8

高度为 h 的 AVL 最少结点数怎样递推?(2012 统考真题)

最少结点 AVL 的两棵子树高度应为 \(h-1\) 与 \(h-2\):

\[ N_h=N_{h-1}+N_{h-2}+1, \]

按本书层高口径取 \(N_1=1,N_2=2\)。递推得高度 6、所有非叶结点平衡因子均为 1 时共有 20 个结点。

💡 本质是“在仍平衡的前提下让两边尽可能少”,因此取允许的最大高度差 1。

回源 · PDF 第 310 页 · b_310_11;PDF 第 310 页 · b_310_12;PDF 第 310 页 · b_310_13;PDF 第 311 页 · b_311_0;PDF 第 311 页 · b_311_1

删除结点再插回,BST 与 AVL 为什么都不保证恢复原树?(2013、2019 统考真题)

  • BST:删叶结点再按原规则插回可恢复;删非叶结点时常由前驱/后继替代,原结点再插回成为叶结点,形态通常改变。
  • AVL:删除和重新插入都可能触发旋转;删叶也可能改变,删非叶也可能因后续旋转恰好恢复,所以只能讨论“可能”,不能下绝对结论。

⚠️ 看到“必然相同、必然不同”先找反例;AVL 比普通 BST 多一层旋转影响。

回源 · PDF 第 311 页 · b_311_2;PDF 第 311 页 · b_311_3;PDF 第 311 页 · b_311_11;PDF 第 311 页 · b_311_12;PDF 第 311 页 · b_311_13;PDF 第 312 页 · b_312_1;PDF 第 312 页 · b_312_2;PDF 第 312 页 · b_312_4

中序得到降序的“AVL”题,为什么必须按统考题设口径作答?(2015 统考真题)

多数教材把 AVL 定义为高度平衡的 BST,中序应升序;但本题命题口径把“平衡二叉树”只按高度平衡理解,因此允许中序降序。

按题设可推出:最大元素没有左子树,但未必是叶结点;最后插入结点经旋转后也未必仍是叶结点。教材答案据此选 D。

⚠️ 考试遇到材料内部约定与常规定义冲突时,先明确“本题按题设/教材口径”,不要擅自改题。

回源 · PDF 第 311 页 · b_311_7;PDF 第 311 页 · b_311_8

BST 图中的未知关键字和整棵子树范围怎样推?(2018、2024 统考真题)

把每个祖先带来的上下界同时保留:左子树继承上界,右子树继承下界;越往下区间只会继续收窄。

  • 2018:先写出图的中序序列,再由递增性比较未知关键字。
  • 2024:子树 T 同时受多个祖先限制,教材综合得到其中任意 \(x\) 满足 \(k_3<x<k_2\)。

💡 一棵子树不是只和直接父结点比,还必须满足所有祖先的范围约束。

回源 · PDF 第 311 页 · b_311_9;PDF 第 311 页 · b_311_10;PDF 第 313 页 · b_313_0;PDF 第 313 页 · b_313_1

红黑树选择题中,哪些绝对化表述最容易出错?(7.3 普通选择题 16~18)

  • AVL 高度更严格,通常查询效率优于同规模红黑树;红黑树的优势主要是增删调整较少,不能把方向说反。
  • 两者查找、插入、删除的渐近复杂度都是 \(O(\log n)\);但按本书删除流程,红黑树删除的旋转次数可能超过 2 次。
  • 红黑树从任一结点到最远叶与最近叶的路径长度之比不超过 2,这是“适度平衡”,不是 AVL 的高度差不超过 1。
  • 若所有内部结点都是黑色,为满足各路径黑高相同,树必须是满二叉树;但以红结点为根截下的子树不满足“根为黑色”,不能直接称为红黑树。

⚠️ 做性质判断时,逐条回到“根叶黑、红不相邻、各路黑高相同”,少凭“看起来平衡”下结论。

回源 · PDF 第 308 页 · b_308_18;PDF 第 308 页 · b_308_19;PDF 第 308 页 · b_308_20;PDF 第 308 页 · b_308_21;PDF 第 309 页 · b_309_0;PDF 第 309 页 · b_309_1;PDF 第 309 页 · b_309_2

m 阶 B 树定义题怎样逐项核对而不被某张具体图误导?(2009 统考真题)

逐项核对四条数量边界:结点关键字数比子树数少 1;根若非终端至少 2 棵子树;除根外非终端至少 \(\lceil m/2\rceil\) 棵子树;所有外部失败结点在同层。

⚠️ 某棵具体 B 树可能同时满足 4 阶、5 阶、6 阶的上下界,不能因为“图中最大分支数是 4”就断言它一定是 4 阶。2009 题中“叶结点彼此必须用指针连接”描述的是 B+ 树特征,不是 B 树定义。

回源 · PDF 第 325 页 · b_325_11;PDF 第 325 页 · b_325_12

B 树的最少/最多关键字或结点数,怎样按层建立上下界?(2013、2014、2018、2021 统考真题)

先分清题目问“关键字数”还是“含关键字的结点数”,再按每层最少/最多分支递推。

  • 2013:高度 2 的 5 阶 B 树,根至少 1 个关键字、第二层至少 2 个结点且各至少 2 个关键字,最少共 5 个。
  • 2014:15 个关键字要让结点数最多,就让每结点尽量只含 1 个关键字,最多 15 个结点。
  • 2018:高度 5 的 3 阶 B 树最少形如满二叉分支,关键字最少为 \(2^5-1=31\)。
  • 2021:3 阶树第 2 层 4 个关键字,为使结点最多,应把它们分散到尽可能多的结点,再让下一层满分支;教材答案为 11 个结点。
回源 · PDF 第 326 页 · b_326_2;PDF 第 326 页 · b_326_4;PDF 第 326 页 · b_326_6;PDF 第 326 页 · b_326_7;PDF 第 326 页 · b_326_12;PDF 第 326 页 · b_326_13;PDF 第 327 页 · b_327_0;PDF 第 327 页 · b_327_1

3 阶/4 阶 B 树连续插入时,分裂和上提怎样逐层传播?(7.4 综合应用题 01、02;2020 统考真题)

先把关键字插到最底层终端结点并保持结点内有序;若插入后关键字数达到 m,就从第 \(\lceil m/2\rceil\) 个关键字处分裂,中间关键字上提父结点;父结点溢出则继续向上分裂。

  • 综合 Q01:3 阶树每结点最多 2 个关键字,插 50、60、70 时分别触发分裂,最终 52 上升为新根。
  • 综合 Q02:插 25 触发一次分裂;插 45 时叶结点和父结点连续分裂。
  • 2020:4 阶树插入给定序列后,根含 6、9。

⚠️ 只有分裂一路传到根并使根分裂,树高才增加 1。

回源 · PDF 第 326 页 · b_326_14;PDF 第 326 页 · b_326_15;PDF 第 328 页 · b_328_0;PDF 第 328 页 · b_328_1;PDF 第 328 页 · b_328_3;PDF 第 328 页 · b_328_5;PDF 第 328 页 · b_328_7;PDF 第 328 页 · b_328_10;PDF 第 328 页 · b_328_12

B 树删除时,什么时候直接删、向兄弟借、与兄弟合并?(7.4 综合应用题 02;2012、2022 统考真题)

先把非终端结点中的删除转化为删除前驱或后继;再看删后是否低于最少关键字数。

  • 兄弟够借:父分隔关键字下移到待调整结点,兄弟的边界关键字上移到父结点,必要时还要随关键字转移对应子树。
  • 兄弟不够借:把当前结点、父分隔关键字和一个兄弟合并;父若下溢继续向上调整。
  • 2012 删除 78 属于左兄弟够借;2022 删除 260 可选前驱或后继并产生多种合法结果,只有根序列 <60,90,110,350> 不可能。
  • 综合 Q02 删除 80 会引发多层合并,但本题调整后根仍有关键字,树高并未下降。一般只有合并使根的关键字数降为 0、原根被删除时,树高才下降 1。

⚠️ 判断合法结果必须同时检查各结点关键字上下界和关键字区间,不能只看根。

回源 · PDF 第 325 页 · b_325_13;PDF 第 326 页 · b_326_0;PDF 第 327 页 · b_327_3;PDF 第 327 页 · b_327_4;PDF 第 327 页 · b_327_5;PDF 第 329 页 · b_329_0;PDF 第 329 页 · b_329_2;PDF 第 329 页 · b_329_3;PDF 第 329 页 · b_329_5

B+ 树与 B 树的差异怎样直接判断应用题?(2016、2017 统考真题)

B+ 树的全部记录信息都在叶结点,非叶结点只作索引;叶结点按关键字顺序链接,所以既能从根多路查找,也能顺序/范围扫描。

  • 2016:能顺序查找、所有关键字信息集中在叶结点,是 B+ 树区别于 B 树的特征。
  • 2017:数据库索引、文件索引适合 B+ 树,因为非叶层更紧凑、磁盘 I/O 代价低,查找路径也更稳定。
回源 · PDF 第 326 页 · b_326_8;PDF 第 326 页 · b_326_9;PDF 第 326 页 · b_326_10;PDF 第 326 页 · b_326_11

B 树的插入、删除、查找是否一定到“叶结点”?(2023 统考真题)

按本书答案与统考术语作答:

  • 插入可能把分裂一路传到根,故可能增高。
  • 删除最终会转化到最底层终端结点处理,教材据此认为会导致叶结点变化。
  • 查找成功可在内部结点提前结束,不总要到底层。
  • 新关键字最初插在底层,但分裂时可能上提,不保证最终仍在叶结点。

⚠️ 本题把最底层终端结点称为“叶结点”,与本书正文常把外部失败结点称叶结点的口径不同;考场以题设为准。

回源 · PDF 第 327 页 · b_327_6;PDF 第 327 页 · b_327_7;PDF 第 327 页 · b_327_8;PDF 第 327 页 · b_327_9

7 个关键字能形成多少种不同 4 阶 B 树,怎样按树高与根关键字数分类?(2025 统考真题)

按树高分类,再按根含 1、2、3 个关键字分配剩余关键字:

  • 两层:根含 1 个时分配 (3,3) 共 1 种;根含 2 个时三子结点分配 (3,1,1) 或 (2,2,1),计排列共 6 种;根含 3 个时四子结点各 1 个,共 1 种。
  • 三层:只有根和第 2 层两个结点都各含 1 个关键字、底层四结点各 1 个的最小结构,共 1 种。

总数 \(1+6+1+1=9\)。

回源 · PDF 第 327 页 · b_327_10;PDF 第 327 页 · b_327_11

用 B 树做磁盘索引时,阶数和索引页数怎样由页块大小反推?(7.4 综合应用题 03)

设 m 阶 B 树结点最多有 \(m-1\) 个关键字与记录地址、m 个子树指针,另有关键字计数域。按题中每项 5B、计数 2B:

\[ (2(m-1)+m)\times5+2\le4000, \]

得 \(m\le267\),取 267 阶。

20000000 条记录、每页 20 条,共 1000000 个数据页;每索引结点可容纳 133~266 个索引项,因此索引部分约需 3760~7519 个页块。

⚠️ 计算时要按题设区分 B 树与 B+ 树:B 树索引项可分布在各层,B+ 树完整记录索引集中在叶层。

回源 · PDF 第 329 页 · b_329_6;PDF 第 329 页 · b_329_7;PDF 第 329 页 · b_329_8;PDF 第 329 页 · b_329_9;PDF 第 329 页 · b_329_10

高度为 h 的 B 树插入一次,最坏读写和新结点数怎样计算?(7.4 普通选择题 11)

按题设“根未读入内存,读过的结点一直留在内存”计算最坏情况:查找插入位置需沿根到最底层读 h 个结点;若分裂逐层传到根,每层分裂要写回 2 个结点,根分裂后形成新根还要再写 1 次。

  • 最多新产生 \(h+1\) 个结点。
  • 最多写磁盘 \(2h+1\) 次,读磁盘 h 次,总读写次数为 \(3h+1\)。
  • 只有分裂传到根并使根分裂时树高才增加;某个普通结点分裂不代表树高必增。
回源 · PDF 第 325 页 · b_325_5;PDF 第 325 页 · b_325_6

提高散列表效率要同时看哪三个因素?(2011、2022 统考真题)

散列表 ASL 主要受三者影响:散列函数是否均匀、冲突处理方法、装填因子 \(\alpha=n/m\)。

  • \(\alpha\) 越大,表越满,冲突概率通常越高。
  • 合适的冲突策略可减轻聚集。
  • ASL 不直接由“表中已有记录数 n”或“表长 m”单独决定;同一 \(\alpha\) 下仍会因函数和策略不同而变化。
回源 · PDF 第 337 页 · b_337_23;PDF 第 337 页 · b_337_24;PDF 第 338 页 · b_338_0;PDF 第 338 页 · b_338_12;PDF 第 338 页 · b_338_13

堆积为什么增大 ASL?线性探测与二次探测的覆盖能力有何不同?(2014、2025 统考真题)

线性探测的探查序列连续,非同义词的探查路径也会互相交织,形成长的连续占用区,即堆积;它会直接增大平均查找长度。

  • 线性探测会遍历整张表,所以只要表未满,一定能找到空位。
  • 二次探测跳跃探查,可减轻堆积,但可能只覆盖部分地址;即使表未满也不保证找到空位。
  • 两种方法处理的冲突都可能来自同义词或非同义词,不能用“一定”限定。
回源 · PDF 第 336 页 · b_336_13;PDF 第 336 页 · b_336_14;PDF 第 338 页 · b_338_1;PDF 第 338 页 · b_338_2;PDF 第 338 页 · b_338_19;PDF 第 338 页 · b_338_20;PDF 第 339 页 · b_339_0

线性探测散列表的查找成功 ASL 怎样逐元素计算?(2018 统考真题)

先按插入顺序构造表;每个关键字的成功查找长度就是从其初始散列地址开始,直到命中它所经历的关键字比较次数。

本题 22、43、15 的比较次数分别为 1、2、3,因此

\[ \mathrm{ASL}_{\text{成功}}=(1+2+3)/3=2. \]

⚠️ 不能直接用“最终下标 − 初始下标”,因为探查可能回绕;应按真实探查序列计数。

回源 · PDF 第 338 页 · b_338_3;PDF 第 338 页 · b_338_4;PDF 第 338 页 · b_338_5;PDF 第 338 页 · b_338_6

线性探测的失败 ASL 为什么按散列函数值域平均,而不是按表长平均?(2019 统考真题)

失败查找先由 \(H(key)\) 产生初始地址,再沿探查序列直到遇到真正空位。题中 \(H(key)=key\%7\),初始地址只有 0~6 七种,即使表长为 11,也只应对这 7 种等可能起点平均。

各起点失败比较次数为 9、8、7、6、5、4、3,所以

\[ \mathrm{ASL}_{\text{失败}}=42/7=6. \]

⚠️ “分母看散列函数可能产生多少个初始地址”,不是机械写表长。

回源 · PDF 第 338 页 · b_338_7;PDF 第 338 页 · b_338_8;PDF 第 338 页 · b_338_9;PDF 第 338 页 · b_338_10;PDF 第 338 页 · b_338_11

开放定址法删除为什么要留墓碑标记?拉链法为什么可物理删除?(7.5 综合应用题 01;2023 统考真题)

开放定址中,某位置可能位于其他关键字的探查路径上;若改成真正空位,后续查找会提前停止。因此只能标为“已删除”,查找遇到墓碑仍要继续。

拉链法的同义词都在独立链表中,删除某结点只需断链,不会截断其他散列地址的查找路径,所以可物理删除。

2023 题删除 25 后,失败查找仍跨过删除标记,教材算得失败 ASL 为 1.8。

回源 · PDF 第 338 页 · b_338_14;PDF 第 338 页 · b_338_15;PDF 第 338 页 · b_338_16;PDF 第 338 页 · b_338_17;PDF 第 338 页 · b_338_18;PDF 第 339 页 · b_339_1;PDF 第 339 页 · b_339_2;PDF 第 339 页 · b_339_3

怎样判断一个表达式能否作为“好散列函数”?(7.5 综合应用题 02)

至少检查三点:返回值始终落在 [0,n-1]、同一 key 每次结果确定、地址分布尽量均匀。

  • key/n 可能越界,不能直接用。
  • 常数 1 虽能映射到表内,但所有关键字冲突,不是好函数。
  • 含每次变化的 random(n),同一 key 地址不确定,无法正常查找。
  • key % p(n) 且 p 为不大于 n 的最大素数,是教材认可的好方法。
回源 · PDF 第 339 页 · b_339_4;PDF 第 339 页 · b_339_5

同一组关键字用线性探测和链地址法时,成功/失败 ASL 为什么不同?(7.5 综合应用题 03)

两种方法的初始散列地址相同,但冲突后的组织方式不同,所以比较路径不同。

  • 线性探测:成功 ASL 按每个关键字真实探查次数平均,本题 \(21/8\);失败从 0~10 各起点探测到空位,本题 \(47/11\)。
  • 链地址:成功按链内关键字比较次数平均,本题 \(13/8\);失败口径若把空指针也算一次,本题 \(19/11\)。

⚠️ 失败 ASL 有“比较到空结点也计一次”和“只计关键字比较”两种口径,必须服从题目或教材说明。

回源 · PDF 第 339 页 · b_339_6;PDF 第 339 页 · b_339_8;PDF 第 339 页 · b_339_9;PDF 第 339 页 · b_339_16;PDF 第 339 页 · b_339_18;PDF 第 340 页 · b_340_0;PDF 第 340 页 · b_340_1;PDF 第 340 页 · b_340_3;PDF 第 340 页 · b_340_5;PDF 第 340 页 · b_340_6;PDF 第 340 页 · b_340_8

给定装填因子并用链地址法时,怎样确定表长、模数和 ASL?(7.5 综合应用题 04)

先由 \(\alpha=n/N\) 求表长 \(N\),再取不大于 N 的最大素数 P 作为除留余数法模数。题中 \(n=11,\alpha=0.73\),得 \(N\approx15,P=13\),故 \(H(key)=key\%13\)。

构造 13 条同义词链后,成功 ASL 按各关键字在链内的比较次数加权;失败若题目明确“只计与关键字比较”,则空链贡献 0。本题成功 ASL \(18/11\),失败 ASL \(11/13\)。

回源 · PDF 第 340 页 · b_340_9;PDF 第 340 页 · b_340_10;PDF 第 340 页 · b_340_11;PDF 第 340 页 · b_340_13;PDF 第 341 页 · b_341_0;PDF 第 341 页 · b_341_1

已知线性探测的 ASL 上限,怎样反推装填因子和最小表长?(7.5 普通选择题 06、07)

若题目直接给出线性探测成功查找的教材公式

\[ \mathrm{ASL}_{成功}=\frac12\left(1+\frac{1}{1-\alpha}\right), \]

先由 ASL 上限解出 \(\alpha\),再用 \(\alpha=n/m\) 反推表长。200 个元素且 ASL 不超过 1.5 时,\(alpha\le1/2\),故 \(m\ge400\)。

若 K 个关键字全为同义词并依次线性探测,最少探测次数为

\[ 1+2+\cdots+K=\frac{K(K+1)}2. \]

⚠️ 公式题按题给模型计算;若题目给出具体关键字序列,则必须实际构表逐项数比较次数。

回源 · PDF 第 336 页 · b_336_17;PDF 第 336 页 · b_336_18;PDF 第 337 页 · b_337_0;PDF 第 337 页 · b_337_1;PDF 第 337 页 · b_337_2;PDF 第 337 页 · b_337_3

链地址法查找路径为什么一定全是同义词,而线性探测不一定?(7.5 普通选择题 12、13)

  • 链地址法把同一初始散列地址的关键字放入同一链表,因此在某条链上成功查找时,经过的关键字一定互为同义词。
  • 线性探测会把冲突元素向后搬移,其他初址的探查序列又可能经过这些位置,所以途中比较的关键字不一定都是同义词。
  • 若 \(H(key)=key\bmod17\),函数值域是 0~16,对应 17 条链和下标 0~16 的链首指针数组。

⚠️ “同义词冲突”与“堆积”不是同一概念;线性探测尤其容易让不同初址的探查路径交织。

回源 · PDF 第 337 页 · b_337_11;PDF 第 337 页 · b_337_12;PDF 第 337 页 · b_337_13;PDF 第 337 页 · b_337_14

双散列探测怎样从固定步长生成整条查找路径?(7.5 综合应用题 05)

先算 \(H_0(key)\),再由第二函数得到该关键字固定的步长;发生冲突后反复累加同一步长并模表长,直到空位或命中。

本题 27 的初址为 1,步长由 REV(28)%11+1 得到,依次探测 1、7、0,最终放入 0。按每个关键字的真实比较次数,成功 ASL 为 \(11/8\)。

⚠️ 双散列不是每次重新生成一个无关步长;对同一 key 的探查序列必须可重现。

回源 · PDF 第 341 页 · b_341_2;PDF 第 341 页 · b_341_3;PDF 第 341 页 · b_341_4;PDF 第 341 页 · b_341_5;PDF 第 341 页 · b_341_6

线性探测综合题怎样从装填因子反推表长并计算两种 ASL?(2010 统考真题)

7 个关键字、装填因子 0.7,先得表长 \(m=10\);再按 \(H(key)=3key\bmod7\) 算初址,用模 10 的线性探测找空位。

  • 成功 ASL:按 7 个表中关键字各自比较次数平均,教材为 \(12/7\)。
  • 失败 ASL:初始地址只可能是 0~6,按这 7 个起点探测到空位的次数平均,教材为 \(18/7\)。

⚠️ 散列函数的模数 7 决定失败 ASL 的等可能起点,散列表长度 10 决定线性探测如何回绕,两者不能混用。

回源 · PDF 第 341 页 · b_341_7;PDF 第 341 页 · b_341_8;PDF 第 341 页 · b_341_10;PDF 第 341 页 · b_341_12;PDF 第 341 页 · b_341_14;PDF 第 341 页 · b_341_16

平方探测综合题怎样构表、给出比较序列并确认失败地址?(2024 统考真题)

严格按 \(H_k=(H_0+k^2)\%11\),取 \(k=1,2,3,\dots\) 的正平方序列:

  • 构表后装填因子为 \(7/11\)。
  • 查 14:依次比较 3、18、14。
  • 查 8:从初址 2 出发,依次探测 2、3、6、0、7;地址 7 为空,故在 7 确认失败。

⚠️ 本题明确只用 \(+k^2\),不要擅自加入教材另一种常见的 \(\pm k^2\) 序列。

回源 · PDF 第 341 页 · b_341_17;PDF 第 342 页 · b_342_0;PDF 第 342 页 · b_342_1;PDF 第 342 页 · b_342_2;PDF 第 342 页 · b_342_3

【原书归纳总结与思维拓展】第7章

各类查找题的 ASL 能否统一成一套“概率 × 比较次数”框架?

可以。成功时对已有元素求

\[ \mathrm{ASL}_{成功}=\sum p_i c_i; \]

失败时对由已有元素划分出的失败区间或可能初址求

\[ \mathrm{ASL}_{失败}=\sum q_j c'_j. \]

真正的难点不是公式,而是确定样本空间:折半失败看 \(n+1\) 个失败区间;开放定址失败看散列函数可能产生的初始地址;链地址还要先确认空指针是否计一次。

回源 · PDF 第 342 页 · b_342_4;PDF 第 342 页 · b_342_5;PDF 第 342 页 · b_342_6;PDF 第 342 页 · b_342_7;PDF 第 342 页 · b_342_8;PDF 第 342 页 · b_342_10

手算查找题时,怎样按“结构—路径—次数—平均”四步避免乱套公式?

  1. 结构:先构造判定树、BST/B 树或散列表。
  2. 路径:逐个标出成功路径及每个失败入口。
  3. 次数:在图上写每个元素/区间的真实比较次数。
  4. 平均:最后才按题给概率求加权平均。

⚠️ 不同结构的失败样本空间不同。先画结构再数次数,通常比直接背 ASL 公式更可靠。

回源 · PDF 第 342 页 · b_342_5;PDF 第 342 页 · b_342_8

AVL 手算能否用零壹“3+4 重构”辅助?边界在哪里?

可以把失衡路径上的三个关键结点按中序排成小、中、大,并把四棵有序子树按中序接回,用来快速复核旋转后的形态;但考试主答案仍按王道写清 LL/RR/LR/RL 类型、最小不平衡子树和旋转方向。

⚠️ “3+4”只是画图/验图工具:不能替代题目要求的旋转过程,也不能忽略结点平衡因子更新;遇到删除可能连续向上调整时,更不能只重构一次就停止。

回源 · PDF 第 313 页 · b_313_14;PDF 第 313 页 · b_313_16;PDF 第 314 页 · b_314_1;PDF 第 314 页 · b_314_3

散列题中有哪些“题设口径优先”的高风险点?

  • 散列失败 ASL 有“空位置也算一次”和“只算关键字比较”两种口径;按题目明示。
  • 平方探测有 +k² 与 ±k² 两种序列;按题给公式,不自行补项。
  • 失败 ASL 的等可能起点由散列函数值域决定,不一定等于散列表的全部下标。
回源 · PDF 第 340 页 · b_340_7;PDF 第 340 页 · b_340_8;PDF 第 342 页 · b_342_3;PDF 第 342 页 · b_342_10

“超过一半的元素”为什么能用成对抵消做到 O(n)?(思维拓展)

若某数出现次数超过一半,每次删除两个不同的数后,它在剩余序列中仍占多数。扫描时维护候选与计数:相同加一,不同减一,计数归零就换候选;最后再扫描一次验证候选是否确实超过一半。

时间 \(O(n)\)、空间 \(O(1)\)。这与第2章主元素题同一方法;本章思维拓展从“查找”角度再次解释了抵消不变量。

回源 · PDF 第 342 页 · b_342_11;PDF 第 342 页 · b_342_12;PDF 第 342 页 · b_342_13;PDF 第 342 页 · b_342_14;PDF 第 342 页 · b_342_15

【易混点】第7章成对概念对照

概念 A 概念 B 一句话切分
静态查找表 动态查找表 顺序/折半 vs BST;散列两者皆可
一般表顺序查找 有序表顺序查找 失败要比 n+1 次 vs 失败可提前返回,n/2 + n/(n+1)
有序表顺序查找 折半查找 ⚠️ 可用链式存储 vs ⚠️ 只能顺序存储
折半查找判定树 BST 唯一 vs 形态取决于插入顺序
折半查找 BST 静态表更优 vs 动态表更优(增删只改指针)
ASL 成功 ASL 失败 算到目的结点 vs 算到失败结点的父结点
分块查找 s = √n 索引顺序表 ASL 最小值 √n + 1
平衡因子 黑高 左减右高度差,取 −1/0/1 vs 到叶结点路径上的黑结点数
AVL 插入调整 AVL 删除调整 只调一次 vs ⚠️ 可能一路回溯到根
LL/RR LR/RL 同向单旋 vs 异向双旋
AVL 红黑树 高度平衡、查找快 vs 适度平衡、增删调整少
B 树叶结点(本书) B 树叶结点(统考) ⚠️ 失败结点 vs ⚠️ 最底层终端结点
B 树 n 关键字 B+ 树 n 关键字 n+1 棵子树 vs n 棵子树
B 树关键字数范围 B+ 树关键字数范围 ⌈m/2⌉−1 ~ m−1 vs ⌈m/2⌉ ~ m
B 树查找 B+ 树查找 中途可命中提前结束 vs 必须走到叶结点
兄弟够借 兄弟不够借 父子换位法 vs 与兄弟和父关键字合并
开放定址法 拉链法 ⚠️ 不能物理删除,只能逻辑删除 vs 适合频繁增删
线性探测 平方探测 会堆积 vs 避免堆积且至少覆盖一半地址,但未必覆盖全部

【必背数字】第7章

数字 含义
(n+1)/2 / n+1 顺序查找 ASL 成功 / 失败
n/2 + n/(n+1) 有序表顺序查找 ASL 失败
⌈log₂(n+1)⌉ / O(log₂n) 折半查找判定树高度 / 时间复杂度
n 个圆形结点 + n+1 个方形失败结点 折半查找判定树的构成
3 / 11/3 教材 11 元素折半查找的 ASL 成功 / 失败
√n + 1 分块查找 s = √n 时的最小 ASL
−1、0、1 AVL 的平衡因子取值
nₕ = nₕ₋₂ + nₕ₋₁ + 1 AVL 最少结点递推;n₅ = 12
2log₂(n+1) 红黑树高度上界
2^h − 1 ~ 2^(2h) − 1 黑高为 h 的红黑树内部结点数范围
m−1 / ⌈m/2⌉−1 B 树结点关键字数上限 / 下限
log_m(n+1) ≤ h ≤ log_⌈m/2⌉((n+1)/2) + 1 B 树高度范围
n + 1 B 树含 n 个关键字时的外部叶结点数
第 ⌈m/2⌉ 个关键字 B 树分裂时上提的位置
4k + 3 的素数 平方探测法对表长的要求
α = n/m 装填因子;ASL 主要依赖它
2.5 教材线性探测算例的 ASL

【口诀速记】第7章

维度 口诀 解释
ASL 两头算 成功算到目标,失败算到失败结点的父 顺序表、折半、BST 的判定树都适用
折半三前提 有序 + 顺序存储 + 取整一致 链表不能折半;向上/向下取整全程只能选一种
分块查找 s = √n 时最省,ASL = √n + 1 块内可无序,块间必须有序
AVL 旋转 同向单旋,异向双旋 LL/RR 单旋;LR/RL 双旋
AVL 定位 先找最小不平衡子树的根 A 再看新结点相对 A 走左左/左右/右右/右左
AVL 最少结点 nₕ = nₕ₋₂ + nₕ₋₁ + 1 n₁=1、n₂=2、n₃=4、n₄=7、n₅=12
红黑树五性质 红不连红,黑高相同,根叶皆黑 高度上界 2log₂(n+1)
B 树两个界 ⌈m/2⌉−1 到 m−1 动手前先把这两个数算出来
B 树增删 超上限中间上提,低下限先借后并 分裂取第 ⌈m/2⌉ 个关键字;兄弟 ≥⌈m/2⌉ 才够借
B vs B+ B 树子树多一个,B+ 关键字全在叶 n 个关键字:B 树 n+1 棵子树,B+ 树 n 棵
散列删除 开放定址只能逻辑删除 物理删除会截断同义词的查找路径
回源 · PDF 第 276 页 · b_276_3;PDF 第 276 页 · b_276_4

【解题路线】第7章:查找题怎么下手

  • ① 算 ASL 一律先画判定树(顺序表 / 折半 / BST 都有判定树):⚠️ 成功算到目标结点的路径结点数;失败算到失败结点的父结点
  • ② 折半查找题 → ⚠️ 先确认表是否有序、是否顺序存储;取整方式全程保持一致;判定树是平衡二叉树,高度 ⌈log₂(n+1)⌉
  • ③ AVL 调整 → ⚠️ 先定位最小不平衡子树的根 A,再看新结点相对 A 走的是 左左 / 左右 / 右右 / 右左 → LL / LR / RR / RL
  • ④ B 树题 → ⚠️ 动手前先算出 ⌈m/2⌉−1(下限)和 m−1(上限)两个数:
  • 插入超上限 → 从第 ⌈m/2⌉ 个关键字处分裂,中间那个上提
  • 删除低于下限 → 先看兄弟够不够借(≥⌈m/2⌉ 就父子换位),不够借就合并
  • ⑤ 散列题 → 先按冲突处理方法把表构造出来,再分别算两个 ASL:⚠️ 成功按各元素的比较次数平均,失败按各初始地址探测到空单元的次数平均

⚠️ 三个易失分点:开放定址法只能逻辑删除;平方探测法要求表长是 4k+3 的素数;B 树的"叶结点"在本书和统考真题中定义不同。

回源 · PDF 第 276 页 · b_276_5;PDF 第 276 页 · b_276_6