ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 알고리즘...78
    일지 2021. 11. 1. 21:29

    B 트리 삭제 메서드 구현

    언더 플로우 처리를 구현한다.

     

    BTree

    /// <summary>
    /// 언더플로우가 발생한 노드를 정리한다.
    /// </summary>
    /// <param name="node">언더 플로우가 발생한 노드</param>
    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->prev != nullptr)
    			{
    				key->prev->right = mergeNode;
    			}
    			if (key->next != nullptr)
    			{
    				key->next->left = mergeNode;
    			}
    
    			if (parent == _root)
    			{
    				parent->Delete(key);
    				_nodeManager.Push(parent);
    				_root = mergeNode;
    			}
    			else if (!parent->Delete(key))
    			{
    				ClearUnderflow(parent);
    			}
    		}
    	}
    }
    
    /// <summary>
    /// 주어진 키를 기준으로 노드를 병합한다.
    /// </summary>
    /// <param name="node">병합할 노드</param>
    /// <param name="lsKey">왼쪽 부모키</param>
    /// <param name="rsKey">오른쪽 부모키</param>
    /// <returns>병합된 노드</returns>
    BTreeNode* BTree::MergeNodeWithKey(BTreeNode* node, BTreeNodeKey* lsKey, BTreeNodeKey* rsKey)
    {
    	BTreeNodeKey* mergeKey{ nullptr };
    	BTreeNode* mergeNode{ nullptr };
    
    	if (rsKey != nullptr)
    	{
    		mergeKey = rsKey;
    		mergeNode = rsKey->right;
    	}
    	else
    	{
    		mergeKey = lsKey;
    		mergeNode = lsKey->left;
    	}
    
    	while (node->size > 0)
    	{
    		BTreeNodeKey* key{ node->GetSmallestKey() };
    		mergeNode->Insert(key);
    	}
    	mergeNode->Insert(mergeKey->value);
    
    	_nodeManager.Push(node);
    
    	return mergeNode;
    }

     

    완료 후 삽입, 삭제 테스트 중 삽입에서 무한 루프에 빠지는 경우를 발견했다. 디버깅을 해 봐야 할 것 같다.

    댓글

Designed by Tistory.