This commit is contained in:
e2hang
2025-08-26 19:21:23 +08:00
parent fe9d51456b
commit 3eb93c256c
3 changed files with 434 additions and 1 deletions

View File

@@ -131,5 +131,169 @@ inline bool BTree<T>::search(Node<T>* _node, const T& _key)
template<class T>
inline void BTree<T>::erase(const T& _key)
{
//1-ɾ<><C9BE>Ҷ<EFBFBD><EFBFBD>
if (!root) return; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><EFBFBD><EFBFBD>
// <20><>һ<EFBFBD><D2BB><EFBFBD>ݹ<EFBFBD> lambda <20><>ʵ<EFBFBD><CAB5>ɾ<EFBFBD><C9BE><EFBFBD>߼<EFBFBD>
auto remove = [&](auto&& self, Node<T>* node, const T& key) -> void {
int idx = 0;
// <20>ҵ<EFBFBD><D2B5><EFBFBD>һ<EFBFBD><D2BB> >= key <20><>λ<EFBFBD><CEBB>
while (idx < node->keys.size() && node->keys[idx] < key) idx++;
// ==============================================================
// <20><><EFBFBD><EFBFBD> 1<><31>key <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD> node->keys[idx]
// ==============================================================
if (idx < node->keys.size() && node->keys[idx] == key) {
// ---- 1.1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ҷ<EFBFBD>ӣ<EFBFBD>ֱ<EFBFBD><D6B1>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (node->isLeaf) {
node->keys.erase(node->keys.begin() + idx);
}
// ---- 1.2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>ڵ㣨<DAB5><E3A3A8>Ҷ<EFBFBD>ӣ<EFBFBD>
else {
Node<T>* leftChild = node->children[idx];
Node<T>* rightChild = node->children[idx + 1];
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> t <20><><EFBFBD>ؼ<EFBFBD><D8BC>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
if (leftChild->keys.size() >= t) {
// <20>ҵ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD>Ԫ<EFBFBD>أ<EFBFBD>
Node<T>* cur = leftChild;
while (!cur->isLeaf) cur = cur->children.back();
T pred = cur->keys.back();
// <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><E6BBBB>ǰ key
node->keys[idx] = pred;
// <20>ݹ<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE>ǰ<EFBFBD><C7B0>
self(self, leftChild, pred);
}
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> t <20><><EFBFBD>ؼ<EFBFBD><D8BC>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
else if (rightChild->keys.size() >= t) {
// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>أ<EFBFBD>
Node<T>* cur = rightChild;
while (!cur->isLeaf) cur = cur->children.front();
T succ = cur->keys.front();
// <20>ú<EFBFBD><C3BA><EFBFBD><EFBFBD><EFBFBD><E6BBBB>ǰ key
node->keys[idx] = succ;
// <20>ݹ<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
self(self, rightChild, succ);
}
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB> t-1 <20><><EFBFBD>ؼ<EFBFBD><D8BC>֣<EFBFBD><D6A3>޷<EFBFBD><DEB7><EFBFBD> <20><> <20>ϲ<EFBFBD>
else {
// <20><> key <20>³<EFBFBD><C2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
leftChild->keys.push_back(node->keys[idx]);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> keys ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
leftChild->keys.insert(leftChild->keys.end(),
rightChild->keys.begin(), rightChild->keys.end());
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> children <20><><EFBFBD><EFBFBD>ȥ
if (!leftChild->isLeaf) {
leftChild->children.insert(leftChild->children.end(),
rightChild->children.begin(), rightChild->children.end());
}
// ɾ<><C9BE><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>е<EFBFBD> key <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
node->keys.erase(node->keys.begin() + idx);
node->children.erase(node->children.begin() + idx + 1);
delete rightChild;
// <20><><EFBFBD><EFBFBD><EFBFBD>ںϲ<DABA><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE> key
self(self, leftChild, key);
}
}
}
// ==============================================================
// <20><><EFBFBD><EFBFBD> 2<><32>key <20><><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD> <20><> ȥ<><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// ==============================================================
else {
if (node->isLeaf) return; // <20><>Ҷ<EFBFBD>ӻ<EFBFBD>û<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>У<EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
bool flag = (idx == node->keys.size()); // key <20><><EFBFBD><EFBFBD><EFBFBD>нڵ㶼<DAB5><E3B6BC> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Node<T>* child = node->children[idx];
// ----------------------------------------------------------
// ɾ<><C9BE>֮ǰҪ<C7B0><D2AA>֤ child <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> t <20><><EFBFBD>ؼ<EFBFBD><D8BC>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD>
// ----------------------------------------------------------
if (child->keys.size() < t) {
Node<T>* leftSibling = (idx > 0 ? node->children[idx - 1] : nullptr);
Node<T>* rightSibling = (idx < node->keys.size() ? node->children[idx + 1] : nullptr);
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵܴ<D6B5><DCB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> >= t <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ֵܽ<D6B5>
if (leftSibling && leftSibling->keys.size() >= t) {
// <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> key <20><> child
child->keys.insert(child->keys.begin(), node->keys[idx - 1]);
// <20><><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> key <20><><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>ڵ<EFBFBD>
node->keys[idx - 1] = leftSibling->keys.back();
leftSibling->keys.pop_back();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӽڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD> children
if (!leftSibling->isLeaf) {
child->children.insert(child->children.begin(), leftSibling->children.back());
leftSibling->children.pop_back();
}
}
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵܴ<D6B5><DCB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> >= t <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ֵܽ<D6B5>
else if (rightSibling && rightSibling->keys.size() >= t) {
// <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> key <20><> child
child->keys.push_back(node->keys[idx]);
// <20><><EFBFBD>ֵܵ<D6B5>һ<EFBFBD><D2BB> key <20><><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>ڵ<EFBFBD>
node->keys[idx] = rightSibling->keys.front();
rightSibling->keys.erase(rightSibling->keys.begin());
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӽڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD> children
if (!rightSibling->isLeaf) {
child->children.push_back(rightSibling->children.front());
rightSibling->children.erase(rightSibling->children.begin());
}
}
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ֵܶ<D6B5><DCB6><EFBFBD><EFBFBD><EFBFBD> t <20><> <20>ϲ<EFBFBD>
else {
if (leftSibling) {
// <20>Ѹ<EFBFBD><D1B8>ڵ<EFBFBD>һ<EFBFBD><D2BB> key <20><><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>ֵ<EFBFBD>
leftSibling->keys.push_back(node->keys[idx - 1]);
// <20><> child <20><> keys ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>
leftSibling->keys.insert(leftSibling->keys.end(),
child->keys.begin(), child->keys.end());
if (!child->isLeaf) {
leftSibling->children.insert(leftSibling->children.end(),
child->children.begin(), child->children.end());
}
// <20><><EFBFBD>ڵ<EFBFBD>ɾ<EFBFBD><C9BE> key <20><> child ָ<><D6B8>
node->keys.erase(node->keys.begin() + idx - 1);
node->children.erase(node->children.begin() + idx);
delete child;
child = leftSibling;
}
else if (rightSibling) {
// <20>Ѹ<EFBFBD><D1B8>ڵ<EFBFBD>һ<EFBFBD><D2BB> key <20><><EFBFBD>Ƶ<EFBFBD> child
child->keys.push_back(node->keys[idx]);
// <20><><EFBFBD><EFBFBD><EFBFBD>ֵܵ<D6B5> keys ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> child
child->keys.insert(child->keys.end(),
rightSibling->keys.begin(), rightSibling->keys.end());
if (!rightSibling->isLeaf) {
child->children.insert(child->children.end(),
rightSibling->children.begin(), rightSibling->children.end());
}
node->keys.erase(node->keys.begin() + idx);
node->children.erase(node->children.begin() + idx + 1);
delete rightSibling;
}
}
}
// ----------------------------------------------------------
// <20><>֤ child <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> t <20><> key <20>󣬵ݹ<F3A3ACB5><DDB9><EFBFBD>ȥ
// ----------------------------------------------------------
if (flag && idx > node->keys.size())
self(self, node->children[idx - 1], key);
else
self(self, node->children[idx], key);
}
};
// <20><><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD>߼<EFBFBD>
remove(remove, root, _key);
// ==============================================================
// ɾ<><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5>¸<EFBFBD><C2B8>ڵ<EFBFBD>Ϊ<EFBFBD><CEAA>
// <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> root û<><C3BB> key <20><>
// ==============================================================
if (root->keys.empty()) {
Node<T>* oldRoot = root;
// <20><><EFBFBD><EFBFBD> root <20><>Ҷ<EFBFBD><D2B6> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
if (root->isLeaf) root = nullptr;
else root = root->children[0]; // root <20><>Ψһ<CEA8><D2BB><EFBFBD>ӳ<EFBFBD>Ϊ<EFBFBD>µĸ<C2B5>
delete oldRoot;
}
}