Balance-Tree-Altered

This commit is contained in:
e2hang
2025-08-26 21:39:35 +08:00
parent 3eb93c256c
commit 96738dec6c
19 changed files with 187 additions and 0 deletions

View File

@@ -569,6 +569,142 @@ deleteKey(node, k):
---
✅ 对的,你理解完全正确!我帮你梳理一下:
---
### 在 B-树删除时,如果要删除的关键字 `x->keys[i]` 在**内部节点**
* **前驱predecessor**
* 就是 `x->children[i]` 这个子树中的最大值。
* 为什么?因为 `x->children[i]` 里所有关键字都 **小于** `x->keys[i]`,而前驱就是其中最大的。
* 找法:一路往右孩子走直到叶子,拿到最后一个 key。
* 伪代码:
```cpp
Node<T>* cur = x->children[i];
while (!cur->isLeaf) cur = cur->children.back();
T predecessor = cur->keys.back();
```
* **后继successor**
* 就是 `x->children[i+1]` 这个子树中的最小值。
* 为什么?因为 `x->children[i+1]` 里所有关键字都 **大于** `x->keys[i]`,而后继就是其中最小的。
* 找法:一路往左孩子走直到叶子,拿到第一个 key。
* 伪代码:
```cpp
Node<T>* cur = x->children[i+1];
while (!cur->isLeaf) cur = cur->children.front();
T successor = cur->keys.front();
```
---
### 删除时的策略
* 如果前驱所在子树 `x->children[i]` 有 ≥ t 个 key
* 用前驱替代 `x->keys[i]`,再递归删除前驱。
* 否则如果后继所在子树 `x->children[i+1]` 有 ≥ t 个 key
* 用后继替代 `x->keys[i]`,再递归删除后继。
* 否则(两个子树都只有 t-1 个 key
* 把 `x->keys[i]` 下移到左子树,和右子树合并,再递归删除。
---
📘 **直观理解**
`x->keys[i]` 在父节点,它左边整个子树都比它小,右边整个子树都比它大。
所以前驱就是左子树里最大值,后继就是右子树里最小值。
---
要不要我帮你画一个 **图解例子**(比如 `t=2` 的 B 树,删除一个内部节点的情况),演示「前驱替代」和「后继替代」的区别?
如果你需要,我可以帮你 **写一个完整的 C++ B 树删除函数实现**,直接和你已有的 `BTree` 类整合,并附详细注释。
你希望我帮你写吗?
---
``` html
总结:
1、删除
2、查看是否下溢出
3、下溢出
a.左右节点可以借(大于t - 1)
父亲下来,借的成为父亲
b.不可以借
和兄弟合并
总结得很到位 👍,我帮你整理一下,更系统一些,方便你以后复习 B-树删除算法。
```
---
## 🌳 B-树删除算法总结
### 1. 删除目标
* **在叶子节点找到 key**
👉 直接删除,不涉及复杂调整。
* **在内部节点找到 key**
👉 不能直接删,而是通过 **前驱 / 后继替代** 或 **合并** 来保持 B-树平衡。
---
### 2. 删除步骤总览
1. **删除目标 key**
* 在叶子:直接删。
* 在内部:找前驱或后继替换,再递归删除。
2. **检查是否下溢underflow**
* B-树的每个节点至少要有 `t - 1` 个 key除了根
* 如果某个子节点删除后不足 `t - 1`,则发生下溢。
3. **处理下溢**
* **a. 向兄弟借关键字(兄弟 ≥ t**
* 父节点“下放”一个关键字到下溢的节点,兄弟的关键字“上升”到父节点。
* 保证节点恢复到 ≥ `t - 1`。
* 📌 这是 **旋转rotation** 操作。
* **b. 无法借(兄弟也是 t - 1 → 合并**
* 将下溢节点、父节点中一个关键字、兄弟节点 **合并** 成一个节点。
* 父节点关键字数减少 1。
* 如果父节点变空,整棵树高度减 1根被替换
---
### 3. 前驱 / 后继选择
* **前驱**`x->keys[i]` 的左子树 `x->children[i]` 中的最大值。
* **后继**`x->keys[i]` 的右子树 `x->children[i+1]` 中的最小值。
* 替代规则:
* 左子树有足够关键字(≥ t用前驱替代。
* 否则若右子树有足够关键字(≥ t用后继替代。
* 否则左右子树都不够,执行合并。
---
### 📌 最简总结版(你说的很对)
1. 删除目标 key。
2. 如果节点关键字数 ≥ `t - 1`,不用处理。
3. 如果 < `t - 1`(下溢):
* **能借** → 借兄弟。
* **不能借** → 合并兄弟和父节点关键字。
---
要不要我帮你画一个小例子(`t=2` 的 B-树),演示 **借** 和 **合并** 两种下溢处理,这样你一眼就能看懂?

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -261,3 +261,54 @@
你希望我画吗?
---
没错 ✅,你总结得非常到位。
这是二叉搜索树BST**删除的基本套路**,红黑树只是额外多了颜色和修复步骤而已。
---
### 普通 BST 的删除分类
假设删除的节点是 `z`
1. **没有孩子(叶子)**
→ 直接删。
2. **只有一个孩子**
→ 用孩子替换它。
3. **有两个孩子**
→ 找 **中序后继(右子树最小)** 或 **中序前驱(左子树最大)**
* 把 `y.key` 复制到 `z.key`
* 实际删除 `y`(而 `y` 一定是“最多一个孩子”的情况)。
所以 **情况 3 总是能转化为情况 1 或 2**。
---
### 为什么后继/前驱最多只有一个孩子?
比如用 **后继**(右子树最小的节点)来说明:
* `y` 在 `z.right` 里,且 `y` 是最靠左的。
* 所以 `y` 不可能有左孩子(否则就不是最左的了)。
* 因此 `y` 要么没有孩子,要么只有右孩子。
对称地,用前驱的话,也必然是“没有孩子或只有左孩子”。
---
### 到红黑树这里
红黑树继承了 BST 结构,所以删除逻辑一样:
* 如果 `z` 有两个孩子,**我们实际删的就是它的后继/前驱 `y`**,而不是直接删 `z`。
* 这就是你说的“删除下移”。
真正复杂的地方在于:**如果被删的是黑色节点**,就需要一整套 `fixup` 来维持红黑树的平衡。
---
要不要我帮你把“3 种情况 → 转化为 2 种简单情况”的流程画成一个 **决策图(删除流程图)**?这样会更直观。

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB