일지

알고리즘...64

niamdank 2021. 10. 7. 14:51

B 트리 삽입 함수 구현 시작

먼저 삽입 처리를 수월하게 하기 위해 노드에 삽입 함수를 구현하고 삽입된 키의 개수를 수월하게 관리하기 위해 노드에 현재 키의 개수를 도입한다.

 

BTree.h

/// <summary>
/// B 트리의 노드에서 사용할 키
/// </summary>
struct BTreeNodeKey
{
	BTreeNodeKey() : left(nullptr), value(0), right(nullptr) {}

	void Clear();
	void Set(int data);

	BTreeNode* left;
	int value;
	BTreeNode* right;
};

/// <summary>
/// B 트리에 사용할 노드
/// </summary>
struct BTreeNode
{
	static const size_t TotalKeyCount{ 4 };

	BTreeNode();
	~BTreeNode();

	void Clear();

	bool Insert(int data);

	BTreeNode* parent;
	BTreeNodeKey* keys;
	size_t size;
};

 

BTree.cpp

/// <summary>
/// 노드의 키를 초기화한다.
/// </summary>
void BTreeNodeKey::Clear()
{
	left = nullptr;
	value = 0;
	right = nullptr;
}

/// <summary>
/// 주어진 값을 키에 저장한다.
/// </summary>
/// <param name="data">저장할 값</param>
void BTreeNodeKey::Set(int data)
{
	value = data;
}

/// <summary>
/// B 트리 노드 생성자, key를 정해진 개수만큼 생성한다.
/// </summary>
BTreeNode::BTreeNode()
	: parent(nullptr), size(0)
{
	keys = new BTreeNodeKey[TotalKeyCount];
}

/// <summary>
/// B 트리 소멸자, 생성했던 키를 제거한다.
/// </summary>
BTreeNode::~BTreeNode()
{
	delete[] keys;
}

/// <summary>
/// 노드를 초기화한다.
/// </summary>
void BTreeNode::Clear()
{
	parent = nullptr;
	for (int i = 0; i < TotalKeyCount; i++)
	{
		keys[i].Clear();
	}
}

/// <summary>
/// 노드에 값을 삽입할 수 있으면 삽입하고 true를 반환하고 아니면 false를 반환한다.
/// </summary>
/// <param name="data"></param>
/// <returns>성공 여부</returns>
bool BTreeNode::Insert(int data)
{
	if (TotalKeyCount <= size)
	{
		return false;
	}

	keys[size++].Set(data);

	return true;
}

 

이 과정에서 기존 검색 함수를 조금 더 최적화 할 수 있었다.

 

BTree::Exists

/// <summary>
/// B 트리를 확인하여 주어진 값이 트리에 존재하는지 여부를 반환한다.
/// </summary>
/// <param name="data">확인할 값</param>
/// <returns>존재 여부</returns>
bool BTree::Exists(int data)
{
	BTreeNode* node{ _root };
	while (node != nullptr)
	{
		for (int i = 0; i < node->size; i++)
		{
			if (node->keys[i].value == data)
			{
				return true;
			}

			if (data < node->keys[i].value)
			{
				node = node->keys[i].left;
				break;
			}

			if (node->keys[i].value < data)
			{
				if (i == node->size)
				{
					node = node->keys[i].right;
					break;
				}
				else if(data < node->keys[i + 1].value)
				{
					node = node->keys[i].right;
					break;
				}
			}
		}
	}
	
	return false;
}

 

현재 임시로 루트에 삽입을 하도록 만들었고 이를 일반화한 뒤 오버플로우에 대한 처리를 추가해야 한다.

 

BTree::Insert

/// <summary>
/// 주어진 값을 B 트리에 삽입한다.
/// </summary>
/// <param name="data">삽입할 값</param>
void BTree::Insert(int data)
{
	if (_root == nullptr)
	{
		_root = _nodeManager.Pop();
		if (_root->Insert(data))
		{
			// 오버플로우 처리
			// 일반화
			return;
		}
	}
}