ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 알고리즘...50
    일지 2021. 9. 8. 01:25

    이진 검색 트리 출력 함수 제작

    노드의 깊이와 넓이의 관계를 파악하기 위해 1, 4 를 추가한다.

     

    main.cpp

    #include "Common.h"
    #include "검색트리/BinarySearchTree.h"
    
    int main()
    {
    	int n = 9;
    	int* arr;
    
    	// 동작 테스트를 위한 값
    	//arr = new int[n]{ 2, 4, 6, 8, 10, 9, 7, 5, 3, 1 };
    	arr = new int[n]{ 10, 5, 20, 3, 7, 15, 25, 1, 4 };
    
    	BinarySearchTree tree;
    	for (int i = 0; i < n; i++)
    	{
    		tree.Insert(arr[i]);
    	}
    	tree.PrintBinarySearchTree();
    
    	//tree.Delete(5);
    	//tree.PrintBinarySearchTree();
    
    	// 출력하고 싶은 모양
    	std::cout << "         10\n";
    	std::cout << "    ┌────┴────┐\n";
    	std::cout << "    5         20\n";
    	std::cout << "  ┌─┴─┐     ┌─┴─┐\n";
    	std::cout << "  5   20    5   20\n";
    	std::cout << "┌─┴─┐\n";
    	std::cout << "1   4\n";
    
    	delete[] arr;
    }

     

    실행결과

           10
    ┌──────┴──────┐
         5       20
    ┌────┴────┐┌─┴─┐
      3  71525
    ┌─┴─┐
    
    
             10
        ┌────┴────┐
        5         20
      ┌─┴─┐     ┌─┴─┐
      5   20    5   20
    ┌─┴─┐
    1   4

     

    엔터 처리가 잘못됐다. 항상 가득 찬 상태의 이진 검색 트리로 처리하다 보니 잘못 생각한 부분이 있었다.

    이 문제를 처리하기 위해 map을 도입했다.

     

    BinarySearchTree.h

    #pragma once
    #include "../Common.h"
    #include <string>
    #include <queue>
    #include <map>
    
    using std::string;
    using std::queue;
    using std::map;
    
    /// <summary>
    /// 이진 검색 트리에 사용할 노드
    /// </summary>
    struct BinarySearchNode
    {
    	BinarySearchNode() : data{ 0 }, parent{ nullptr }, 
    		left{ nullptr }, right{ nullptr } {}
    	BinarySearchNode(int data) : data{ data }, parent{ nullptr }, 
    		left{ nullptr }, right{ nullptr } {}
    
    	void Clear()
    	{
    		data = 0;
    		parent = nullptr;
    		left = nullptr;
    		right = nullptr;
    	}
    
    	int GetMaxDepth()
    	{
    		int leftMaxDepth{ left != nullptr ? left->GetMaxDepth() : 0 };
    		int rightMaxDpth{ right != nullptr ? right->GetMaxDepth() : 0 };
    		return (leftMaxDepth > rightMaxDpth ? leftMaxDepth : rightMaxDpth) + 1;
    	}
    
    	int GetCurDepth()
    	{
    		return (parent != nullptr ? parent->GetCurDepth() : 0) + 1;
    	}
    
    	bool HasLeftChild()
    	{
    		return left != nullptr;
    	}
    
    	bool HasRightChild()
    	{
    		return right != nullptr;
    	}
    
    	int data;
    	BinarySearchNode* parent;
    	BinarySearchNode* left;
    	BinarySearchNode* right;
    };
    
    /// <summary>
    /// 이진 검색 트리에서 노드의 재활용을 위한 매니저
    /// </summary>
    class BinarySearchNodeManager
    {
    public:
    	~BinarySearchNodeManager();
    
    	void Push(BinarySearchNode* node);
    	BinarySearchNode* Pop();
    
    private:
    	BinarySearchNode* nodes;
    };
    
    /// <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);
    
    	BinarySearchNode* GetNode(int data);
    
    	bool IsLeftNode(BinarySearchNode* node);
    	bool IsRightNode(BinarySearchNode* node);
    
    	int GetTreeMaxDepth();
    
    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 depth{ _root->GetMaxDepth() };
    
    	for (int i = 1; i <= depth; i++)
    	{
    		_numberMap[i] = "";
    		_stickMap[i] = "";
    	}
    
    	_queue.push(_root);
    	while (!_queue.empty())
    	{
    		BinarySearchNode* node{ _queue.front() };
    		_queue.pop();
    
    		PrintBinarySearchTree(node);
    
    		if (node->left != nullptr)
    		{
    			_queue.push(node->left);
    		}
    		if (node->right != nullptr)
    		{
    			_queue.push(node->right);
    		}
    	}
    
    	for (int i = 1; i <= depth; i++)
    	{
    		std::cout << _numberMap[i] << '\n';
    		std::cout << _stickMap[i] << '\n';
    	}
    	std::cout << "\n\n";
    }
    
    /// <summary>
    /// 이진 검색 트리를 출력한다.
    /// </summary>
    /// <param name="node">현재 출력할 노드</param>
    void BinarySearchTree::PrintBinarySearchTree(BinarySearchNode* node)
    {
    	int targetDepth{ node->GetCurDepth() };
    	int depth{ node->GetMaxDepth() };
    	int width{ (depth - 1) * 5 };
    	int center{ width / 2 };
    
    	string& numberStr{ _numberMap[targetDepth] };
    	string& stickStr{ _stickMap[targetDepth] };
    
    	for (int i = 0; i < width; i++)
    	{
    		numberStr.push_back(' ');
    	}
    	numberStr.append(std::to_string(node->data));
    	for (int i = 0; i < width; i++)
    	{
    		numberStr.push_back(' ');
    	}
    
    	for (int i = 0; i < center; i++)
    	{
    		stickStr.push_back(' ');
    	}
    	if (node->HasLeftChild())
    	{
    		stickStr.append("┌");
    		for (int i = 1; i < center; i++)
    		{
    			stickStr.append("─");
    		}
    	}
    	else
    	{
    		for (int i = 0; i < width; i++)
    		{
    			stickStr.push_back(' ');
    		}
    	}
    
    	if (node->HasLeftChild() || node->HasRightChild())
    	{
    		stickStr.append("┴");
    	}
    
    	if (node->HasRightChild())
    	{
    		for (int i = 1; i < center; i++)
    		{
    			stickStr.append("─");
    		}
    		stickStr.append("┐");
    	}
    	else
    	{
    		for (int i = 0; i < width; i++)
    		{
    			stickStr.push_back(' ');
    		}
    	}
    }

     

    실행결과

                   10
           ┌──────┴──────┐
              5               20
         ┌────┴────┐  ┌─┴─┐
         3     71525
      ┌─┴─┐
    14
    
    
    
             10
        ┌────┴────┐
        5         20
      ┌─┴─┐     ┌─┴─┐
      5   20    5   20
    ┌─┴─┐
    1   4

     

    엔터 처리는 설정이 되었으나 여전히 간격이 적절하지 못하다.

    댓글

Designed by Tistory.