ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 알고리즘...71
    일지 2021. 10. 18. 16:53

    B 트리 삽입 오버플로우 처리

     

    오버 플로우 처리 중 삽입 가능한 형제가 존재한 경우에 대한 처리를 구현한다.

     

    오버 플로우가 발생한 노드의 형제 노드의 위치가 왼쪽인 경우 가장 작은 키를 부모에 넣고 부모의 형제 노드를 가리키는 키와 값을 바꾼 뒤 해당 키를 형제 노드에 삽입하면 된다.

     

    이를 위해 Node의 Insert 함수를 수정하여 Key가 직접 입력된 경우를 적절하게 처리해 주는 함수를 추가한다.

     

    BTreeNodeKey

    /// <summary>
    /// 새 키를 기존 키의 오른쪽에 삽입한다.
    /// </summary>
    /// <param name="newKey">삽입할 키</param>
    void BTreeNodeKey::AddKeyToNext(BTreeNodeKey* newKey)
    {
    	BTreeNodeKey* nextKey{ next };
    	if (nextKey != nullptr)
    	{
    		nextKey->prev = newKey;
    		newKey->next = nextKey;
    	}
    	newKey->prev = this;
    	next = newKey;
    }
    
    /// <summary>
    /// 다른 키와 value를 교환한다.
    /// </summary>
    /// <param name="other">다른 키</param>
    void BTreeNodeKey::SwapValue(BTreeNodeKey* other)
    {
    	int temp{ value };
    	value = other->value;
    	other->value = temp;
    }

     

    BTreeNode

    /// <summary>
    /// 노드에 데이터를 삽입한다.
    /// </summary>
    /// <param name="data">삽입할 데이터</param>
    /// <returns>성공 여부</returns>
    bool BTreeNode::Insert(int data)
    {
    	BTreeNodeKey* newKey{ keyManager->Pop() };
    	newKey->Set(data);
    
    	return Insert(newKey);
    }
    
    /// <summary>
    /// 주어진 키를 노드의 키에 삽입한다.
    /// </summary>
    /// <param name="key">삽입할 키</param>
    /// <returns>성공 여부</returns>
    bool BTreeNode::Insert(BTreeNodeKey* newKey)
    {
    	if (keyRoot == nullptr)
    	{
    		keyRoot = newKey;
    	}
    	else
    	{
    		// 새 값이 노드에서 가장 작은 경우
    		if (newKey->value < keyRoot->value)
    		{
    			keyRoot->AddKeyToPrev(newKey);
    			keyRoot = newKey;
    		}
    		else
    		{
    			BTreeNodeKey* key{ keyRoot };
    			BTreeNodeKey* prevKey{ nullptr };
    
    			while (key != nullptr)
    			{
    				if (newKey->value < key->value)
    				{
    					prevKey = nullptr;
    					key->AddKeyToPrev(newKey);
    					break;
    				}
    
    				prevKey = key;
    				key = key->next;
    			}
    
    			// 새 값이 노드에서 가장 큰 경우
    			if (prevKey != nullptr)
    			{
    				prevKey->AddKeyToNext(newKey);
    			}
    		}
    	}
    
    	size++;
    
    	return size <= TotalKeyCount;
    }
    
    /// <summary>
    /// 가장 작은 키를 노드에서 떼어내 반환한다.
    /// </summary>
    /// <returns>가장 작은 키</returns>
    BTreeNodeKey* BTreeNode::GetSmallestKey()
    {
    	BTreeNodeKey* key{ nullptr };
    	if (keyRoot != nullptr)
    	{
    		key = keyRoot;
    		keyRoot = keyRoot->next;
    		keyRoot->prev = nullptr;
    	}
    	return key;
    }
    
    /// <summary>
    /// 가장 큰 키를 노드에서 떼어내 반환한다.
    /// </summary>
    /// <returns>가장 큰 키</returns>
    BTreeNodeKey* BTreeNode::GetBiggestKey()
    {
    	BTreeNodeKey* key{ nullptr };
    	if (keyRoot != nullptr)
    	{
    		key = keyRoot;
    		while (key->next != nullptr)
    		{
    			key = key->next;
    		}
    
    		BTreeNodeKey* prev{ key->prev };
    		if (prev != nullptr)
    		{
    			prev->next = nullptr;
    			key->prev = nullptr;
    		}
    	}
    	return key;
    }

     

    BTree

    /// <summary>
    /// 오버플로우 발생한 노드를 정리한다.
    /// </summary>
    /// <param name="node">오버 플로우가 발생한 노드</param>
    void BTree::ClearOverflow(BTreeNode* node)
    {
    	bool isDone{ false };
    
    	BTreeNode* p{ node->parent };
    	// 루트 노드가 아닌 경우
    	if (p != nullptr)
    	{
    		BTreeNodeKey* lsKey{ nullptr };
    		BTreeNodeKey* rsKey{ p->keyRoot };
    		while (rsKey != nullptr)
    		{
    			if (rsKey->left == node)
    			{
    				break;
    			}
    			lsKey = rsKey;
    			rsKey = rsKey->next;
    		}
    
    		// 왼쪽 형제가 존재하고 삽입 가능한 경우
    		if (lsKey != nullptr && lsKey->left != nullptr
    			&& lsKey->left->IsAbleToInsert())
    		{
    			BTreeNodeKey* key{ node->GetSmallestKey() };
    			lsKey->SwapValue(key);
    			lsKey->left->Insert(key);
    			isDone = true;
    		}
    		// 오른쪽 형제가 존재하고 삽입 가능한 경우
    		else if (rsKey != nullptr && rsKey->right != nullptr
    			&& rsKey->right->IsAbleToInsert())
    		{
    			BTreeNodeKey* key{ node->GetBiggestKey() };
    			rsKey->SwapValue(key);
    			rsKey->right->Insert(key);
    			isDone = true;
    		}
    	}
    
    	// 삽입 가능한 형제가 없는 경우
    	if (!isDone)
    	{
    
    	}
    }

    댓글

Designed by Tistory.