일지
알고리즘...55
niamdank
2021. 9. 15. 01:46
노드를 연결하는 막대 그리기
이전 계산을 통해 노드 사이의 간격을 알고 있으므로 막대는 다음과 같이 그릴 수 있다.

막대의 경우 현 노드가 왼쪽 자식인지, 오른쪽 자식인지에 따라 처리가 달라지게 된다.
먼저 왼쪽 자식의 처리는 다음과 같이 진행한다.
- 노드와 동일한 공백 입력
- 노드의 크기의 절반 만큼 공백 추가
- 오른쪽 아래 막대 추가
- 노드의 크기의 절반 만큼 가로 막대 추가
- 공백의 절반 - 1 만큼 가로 막대 추가
- 위로 향하는 막대 추가
오른쪽 자식의 처리는 다음과 같이 진행한다.
- 위로 향하는 막대 추가
- 공백의 절반 - 1 만큼 가로 막대 추가
- 노드의 크기의 절반 만큼 가로 막대 추가
- 왼쪽 아래 막대 추가
- 노드의 크기의 절반 만큼 공백 추가
BinarySearchTree.h
/// <summary>
/// 연결 자료구조를 이용한 이진 검색 트리
/// </summary>
class BinarySearchTree
{
public:
~BinarySearchTree();
bool Exists(int data);
const BinarySearchNode& Search(int data);
void Insert(int data);
void Delete(int data);
void PrintBinarySearchTree();
private:
void Insert(BinarySearchNode* parent, int data);
void Delete(BinarySearchNode* node);
void PrintBinarySearchTree(BinarySearchNode* node, int lineWidth);
BinarySearchNode* GetNode(int data);
bool IsLeftNode(BinarySearchNode* node);
bool IsRightNode(BinarySearchNode* node);
int GetTreeMaxDepth();
string GetNodeStick(BinarySearchNode* node, int blankSize);
private:
BinarySearchNode* _root;
BinarySearchNodeManager _nodeManager;
queue<BinarySearchNode*> _queue;
map<int, string> _numberMap;
map<int, string> _stickMap;
};
BinarySearchTree.cpp
/// <summary>
/// 이진 검색 트리를 출력한다.
/// </summary>
void BinarySearchTree::PrintBinarySearchTree()
{
if (_root == nullptr)
{
std::cout << "EMPTY\n";
return;
}
int maxDepth{ _root->GetMaxDepth() };
int maxNodeCount{ static_cast<int>(std::pow(2, maxDepth - 1)) };
int totalCount{ maxNodeCount * 2 + 1 };
int lineWidth{ totalCount * BinarySearchNode::Width };
for (int i = 1; i <= maxDepth; i++)
{
_numberMap[i] = "";
_stickMap[i] = "";
}
_queue.push(_root);
while (!_queue.empty())
{
BinarySearchNode* node{ _queue.front() };
_queue.pop();
PrintBinarySearchTree(node, lineWidth);
if (node->left != nullptr)
{
_queue.push(node->left);
}
else if (!node->isEmpty)
{
_queue.push(_nodeManager.GetEmptyNode(node));
}
if (node->right != nullptr)
{
_queue.push(node->right);
}
else if (!node->isEmpty)
{
_queue.push(_nodeManager.GetEmptyNode(node));
}
if (node->isEmpty)
{
_nodeManager.Push(node);
}
}
for (int i = 1; i <= maxDepth; i++)
{
std::cout << _stickMap[i] << '\n';
std::cout << _numberMap[i] << '\n';
}
std::cout << "\n\n";
}
/// <summary>
/// 주어진 노드에 맞는 막대를 만들어 반환한다.
/// </summary>
/// <param name="node">처리할 노드</param>
/// <returns>막대 노드 문자열</returns>
string BinarySearchTree::GetNodeStick(BinarySearchNode* node, int blankSize)
{
if (node == _root)
{
return "";
}
int halfNodeWidth{ BinarySearchNode::Width / 2 };
int halfBlankSize{ blankSize / 2 };
if (node->isEmpty)
{
int stringLength{ BinarySearchNode::Width + blankSize };
return string(stringLength, ' ');
}
string result;
if (IsLeftNode(node))
{
int leftSpaceCnt{ blankSize + halfNodeWidth
- (BinarySearchNode::Width % 2 == 0 ? 1 : 0) };
result.append(string(leftSpaceCnt, ' '));
result.append("┌");
int rightHypenCnt{ halfBlankSize + halfNodeWidth - 1 };
for (int i = 0; i < rightHypenCnt; i++)
{
result.append("─");
}
result.append("┘");
}
else
{
result.append("└");
int leftHypenCnt{ halfBlankSize + halfNodeWidth - 1 };
for (int i = 0; i < leftHypenCnt; i++)
{
result.append("─");
}
result.append("┐");
result.append(string(halfNodeWidth, ' '));
}
return result;
}
실행결과
_10__
┌─────────────┘└─────────────┐
__5__ _20__
┌───────┘└───────┐ ┌───────┘└───────┐
__3__ __7__ _15__ _25__
┌───┘└───┐
__1__ __4__ _____ _____ _____ _____ _____ _____
__7__
┌─────────────┘└─────────────┐
__4__ _20__
┌───────┘ └───────┐
__3__ _____ _____ _25__
┌───┘
__1__ _____ _____ _____
깔끔한 결과는 아니지만 어느정도 알아볼 수 있는 결과를 얻었다.