일지
알고리즘...82
niamdank
2021. 11. 10. 09:16
B 트리 삭제 메서드, 병합 처리
병합 처리를 구현한 부분 중 leaf 노드와 키를 처리하는 부분에서 키를 노드에서 빼는 과정으로 인해 버그가 발생하여 해당 값을 빼는 게 아니니 최소 값인 keyRoot를 이용하는 것으로 수정했다.
BTree
void BTree::ClearUnderflow(BTreeNode* node)
{
// 노드가 루트인 경우
if (node == _root)
{
if (node->size == 0)
{
_nodeManager.Push(node);
_root = nullptr;
}
}
else
{
bool isDone{ false };
BTreeNode* parent{ node->parent };
BTreeNodeKey* lsKey{ nullptr };
BTreeNodeKey* rsKey{ parent->keyRoot };
while (rsKey != nullptr)
{
if (rsKey->left == node)
{
break;
}
lsKey = rsKey;
rsKey = rsKey->next;
}
// 왼쪽 형제가 존재하고 키 인출 가능한 경우
if (lsKey != nullptr && lsKey->left != nullptr
&& lsKey->left->IsAbleToWithdraw())
{
BTreeNodeKey* key{ lsKey->left->GetBiggestKey() };
lsKey->SwapValue(key);
node->Insert(key);
isDone = true;
}
// 오른쪽 형제가 존재하고 키 인출 가능한 경우
else if (rsKey != nullptr && rsKey->right != nullptr
&& rsKey->right->IsAbleToWithdraw())
{
BTreeNodeKey* key{ rsKey->right->GetSmallestKey() };
rsKey->SwapValue(key);
node->Insert(key);
isDone = true;
}
// 인출 가능한 형제가 없는 경우
if (!isDone)
{
BTreeNodeKey* key{ rsKey != nullptr ? rsKey : lsKey };
BTreeNode* mergeNode{ MergeNodeWithKey(node, lsKey, rsKey) };
if (key != nullptr)
{
if (key->prev != nullptr)
{
key->prev->right = mergeNode;
}
if (key->next != nullptr)
{
key->next->left = mergeNode;
}
if (parent == _root && _root->size == 1)
{
parent->Delete(key);
_nodeManager.Push(parent);
_root = mergeNode;
}
else if (!parent->Delete(key))
{
ClearUnderflow(parent);
}
}
}
}
}
BTreeNode* BTree::GetProperNodeToDelete(int data)
{
BTreeNode* node{ _root };
BTreeNode* leafNode{ nullptr };
while (node != nullptr)
{
if (node->IsContainsData(data))
{
BTreeNodeKey* key{ node->GetKey(data) };
leafNode = node;
while (key->right != nullptr)
{
leafNode = key->right;
key = leafNode->keyRoot;
}
break;
}
BTreeNodeKey* key{ node->keyRoot };
while (key != nullptr)
{
if (data < key->value)
{
node = key->left;
break;
}
else if (key->value < data)
{
if (key->next == nullptr || data < key->next->value)
{
node = key->right;
break;
}
}
key = key->next;
}
}
if (leafNode != nullptr && leafNode != node)
{
BTreeNodeKey* key{ node->GetKey(data) };
BTreeNodeKey* leafKey{ leafNode->keyRoot };
key->SwapValue(leafKey);
node = leafNode;
}
return leafNode;
}
main.cpp
#include "Common.h"
#include "검색트리/BTree.h"
int main()
{
int n = 9;
int* arr;
// 동작 테스트를 위한 값
arr = new int[n]{ 10, 5, 20, 3, 7, 15, 25, 1, 4 };
BTree tree;
for (int i = 0; i < n; i++)
{
tree.Insert(arr[i]);
tree.PrintTree();
}
tree.Delete(5);
tree.PrintTree();
tree.Delete(10);
tree.PrintTree();
tree.Delete(15);
tree.PrintTree();
tree.Delete(1);
tree.PrintTree();
tree.Delete(3);
tree.PrintTree();
tree.Delete(20);
tree.PrintTree();
tree.Delete(7);
tree.PrintTree();
tree.Delete(4);
tree.PrintTree();
tree.Delete(25);
tree.PrintTree();
delete[] arr;
}
실행결과
--------------------
[10]
--------------------
--------------------
[5, 10]
--------------------
--------------------
[5, 10, 20]
--------------------
--------------------
[5]
[3][10, 20]
--------------------
--------------------
[5]
[3][7, 10, 20]
--------------------
--------------------
[7]
[3, 5][10, 15, 20]
--------------------
--------------------
[10]
[3, 5, 7][15, 20, 25]
--------------------
--------------------
[3, 10]
[1][5, 7][15, 20, 25]
--------------------
--------------------
[3, 10]
[1][4, 5, 7][15, 20, 25]
--------------------
--------------------
[3, 10]
[1][4, 7][15, 20, 25]
--------------------
--------------------
[3, 15]
[1][4, 7][20, 25]
--------------------
--------------------
[3, 20]
[1][4, 7][25]
--------------------
--------------------
[4, 20]
[3][7][25]
--------------------
--------------------
[20]
[4, 7][25]
--------------------
--------------------
[7]
[4][25]
--------------------
--------------------
[4, 25]
--------------------
--------------------
[25]
--------------------
--------------------
EMPTY TREE
--------------------