ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 알고리즘...110
    일지 2022. 2. 22. 15:06

    그래프 출력 구현

    Graph_AdjacencyMatrix.h

    #pragma once
    #include "Graph.h"
    #include <algorithm>
    #include <queue>
    #include <stack>
    
    using std::queue;
    using std::stack;
    
    /// <summary>
    /// 그래프의 구성 요소 테스트를 위한 베이스 클래스
    /// </summary>
    class Graph_AdjacencyMatrix : public Graph
    {
    public:
    	Graph_AdjacencyMatrix(GraphOption graphOption = GraphOption::Undirected, size_t size = 10);
    
    	virtual bool AddNode(string name);
    	virtual void AddEdge(string from, string to, int weight = 1);
    	virtual bool RemoveNode(string name);
    	virtual void RemoveEdge(string from, string to);
    	virtual void Clear();
    
    	virtual void PrintGraph(GraphTraversal graphTraversal = GraphTraversal::BFS, string graphName = "Graph_AdjacencyMatrix");
    
    private:
    	void Resize();
    
    	void PrintGraphBFS(size_t nodeIdx);
    	void PrintGraphDFS(size_t nodeIdx);
    
    protected:
    	size_t GetNodeCapacity() { return m_capacity; }
    
    private:
    	int** m_matrix;
    	size_t m_capacity;
    
    	static const int None{ INT_MIN };
    };

     

    Graph_AdjacencyMatrix.cpp

    #include "Graph_AdjacencyMatrix.h"
    
    #pragma region Public Functions
    /// <summary>
    /// 그래프 옵션을 결정하고 그래프의 최초 크기를 설정한다.
    /// </summary>
    /// <param name="graphOption">그래프 옵션</param>
    /// <param name="size">그래프 크기</param>
    Graph_AdjacencyMatrix::Graph_AdjacencyMatrix(GraphOption graphOption, size_t size)
    	: Graph(graphOption)
    {
    	m_capacity = size;
    	
    	m_matrix = new int* [size];
    	for (size_t i = 0; i < size; i++)
    	{
    		m_matrix[i] = new int[size];
    		std::fill_n(m_matrix[i], size, None);
    	}
    }
    
    /// <summary>
    /// 그래프에 노드를 추가한다.
    /// </summary>
    /// <param name="name">추가할 노드 이름</param>
    /// <returns>성공 여부</returns>
    bool Graph_AdjacencyMatrix::AddNode(string name)
    {
    	if (!Graph::AddNode(name))
    	{
    		return false;
    	}
    
    	if (GetNodeCount() >= m_capacity)
    	{
    		Resize();
    	}
    
    	return true;
    }
    
    /// <summary>
    /// 그래프에 에지를 추가한다.
    /// </summary>
    /// <param name="from">시작 노드</param>
    /// <param name="to">끝 노드</param>
    /// <param name="weight">가중치(기본: 1)</param>
    void Graph_AdjacencyMatrix::AddEdge(string from, string to, int weight)
    {
    	size_t fromIdx{ GetNodeIndex(from) }, toIdx{ GetNodeIndex(to) };
    
    	if (fromIdx != -1 && toIdx != -1)
    	{
    		m_matrix[fromIdx][toIdx] = weight;
    
    		if (CurrentGraphOption() == GraphOption::Undirected)
    		{
    			m_matrix[toIdx][fromIdx] = weight;
    		}
    	}
    }
    
    /// <summary>
    /// 그래프에서 노드를 제거한다.
    /// </summary>
    /// <param name="name">제거할 노드 이름</param>
    /// <returns>성공 여부</returns>
    bool Graph_AdjacencyMatrix::RemoveNode(string name)
    {
    	size_t idx{ GetNodeIndex(name) };
    
    	if (!Graph::RemoveNode(name))
    	{
    		return false;
    	}
    
    	for (size_t i = 0; i < m_capacity; i++)
    	{
    		m_matrix[idx][i] = None;
    		m_matrix[i][idx] = None;
    	}
    
    	return true;
    }
    
    /// <summary>
    /// 그래프에서 에지를 제거한다.
    /// </summary>
    /// <param name="from">시작 노드</param>
    /// <param name="to">끝 노드</param>
    void Graph_AdjacencyMatrix::RemoveEdge(string from, string to)
    {
    	size_t fromIdx{ GetNodeIndex(from) }, toIdx{ GetNodeIndex(to) };
    
    	if (fromIdx != -1 && toIdx != -1)
    	{
    		m_matrix[fromIdx][toIdx] = None;
    
    		if (CurrentGraphOption() == GraphOption::Undirected)
    		{
    			m_matrix[toIdx][fromIdx] = None;
    		}
    	}
    }
    
    /// <summary>
    /// 그래프를 초기화한다.
    /// </summary>
    void Graph_AdjacencyMatrix::Clear()
    {
    	Graph::Clear();
    
    	for (size_t i = 0; i < m_capacity; i++)
    	{
    		std::fill_n(m_matrix[i], m_capacity, None);
    	}
    }
    
    /// <summary>
    /// 해시 테이블의 현 상태를 출력한다.
    /// </summary>
    void Graph_AdjacencyMatrix::PrintGraph(GraphTraversal graphTraversal, string graphName)
    {
    	Graph::PrintGraph(graphTraversal, graphName);
    
    	std::cout << "- Graph Edges\n";
    	for (size_t i = 0; i < m_capacity; i++)
    	{
    		std::cout << GetNodeNameAt(i) << " : ";
    		for (size_t j = 0; j < m_capacity; j++)
    		{
    			if (m_matrix[i][j] == None)
    			{
    				continue;
    			}
    			std::cout << GetNodeNameAt(j) << " - ";
    		}
    		std::cout << '\n';
    	}
    	std::cout << "------------------------------------------\n";
    
    	std::cout << "- Graph Traversal from FIRST NODE\n";
    	GraphNode node{ GetFirstNode() };
    	size_t nodeIdx{ GetNodeIndex(node.name) };
    
    	if (node.name == "EMPTY")
    	{
    		std::cout << "EMPTY\n";
    	}
    	else
    	{
    		bool* nodeChecker = new bool[m_capacity] {};
    		if (graphTraversal == GraphTraversal::BFS)
    		{
    			PrintGraphBFS(nodeIdx);
    		}
    		else if (graphTraversal == GraphTraversal::DFS)
    		{
    			PrintGraphDFS(nodeIdx);
    		}
    		delete[] nodeChecker;
    	}
    	std::cout << "\n------------------------------------------\n";
    }
    #pragma endregion
    
    #pragma region Private Functions
    /// <summary>
    /// 그래프의 크기를 두배로 늘린다.
    /// </summary>
    void Graph_AdjacencyMatrix::Resize()
    {
    	size_t tempCapacity{ m_capacity * 2 };
    	int** tempMatrix{ new int* [tempCapacity] };
    	for (size_t i = 0; i < tempCapacity; i++)
    	{
    		tempMatrix[i] = new int[tempCapacity];
    		std::fill_n(tempMatrix[i], tempCapacity, 0);
    	}
    
    	for (size_t i = 0; i < m_capacity; i++)
    	{
    		std::copy_n(m_matrix[i], m_capacity, tempMatrix[i]);
    		delete[] m_matrix[i];
    	}
    	delete[] m_matrix;
    
    	m_capacity = tempCapacity;
    	m_matrix = tempMatrix;
    }
    
    /// <summary>
    /// BFS로 그래프를 출력한다.
    /// </summary>
    void Graph_AdjacencyMatrix::PrintGraphBFS(size_t nodeIdx)
    {
    	bool* nodeChecker = new bool[m_capacity] {};
    	queue<size_t> q;
    	q.push(nodeIdx);
    
    	while (!q.empty())
    	{
    		size_t idx{ q.front() };
    		q.pop();
    
    		if (!nodeChecker[idx])
    		{
    			nodeChecker[idx] = true;
    
    			std::cout << GetNodeNameAt(idx) << " - ";
    			for (size_t i = 0; i < m_capacity; i++)
    			{
    				if (m_matrix[idx][i] != None)
    				{
    					q.push(i);
    				}
    			}
    		}
    	}
    
    	delete[] nodeChecker;
    }
    
    /// <summary>
    /// DFS로 그래프를 출력한다.
    /// </summary>
    void Graph_AdjacencyMatrix::PrintGraphDFS(size_t nodeIdx)
    {
    	bool* nodeChecker = new bool[m_capacity] {};
    	stack<size_t> s;
    	s.push(nodeIdx);
    
    	while (!s.empty())
    	{
    		size_t idx{ s.top() };
    		s.pop();
    
    		if (!nodeChecker[idx])
    		{
    			nodeChecker[idx] = true;
    
    			std::cout << GetNodeNameAt(idx) << " - ";
    			for (size_t i = 0; i < m_capacity; i++)
    			{
    				if (m_matrix[idx][i] != None)
    				{
    					s.push(i);
    				}
    			}
    		}
    	}
    
    	delete[] nodeChecker;
    }
    #pragma endregion

     

    main.cpp

    #include "Common.h"
    #include "그래프/Graph_AdjacencyMatrix.h"
    
    int main()
    {
    	Graph_AdjacencyMatrix graph;
    
    	graph.AddNode("First");
    	graph.AddNode("Second");
    	graph.AddNode("Third");
    	graph.AddNode("Etc");
    
    	graph.AddEdge("First", "Second");
    	graph.AddEdge("Second", "Third");
    	graph.AddEdge("Etc", "First");
    	graph.AddEdge("Etc", "Third");
    
    	graph.PrintGraph();
    }

     

    실행결과_BFS

    ------------------------------------------
    - Class Name            : Graph_AdjacencyMatrix
    - GraphOption           : Undirected
    - GraphTraversal        : BFS
    - Graph Nodes
    Index[0] : First - Index[1] : Second - Index[2] : Third - Index[3] : Etc
    ------------------------------------------
    - Graph Edges
    First : Second - Etc -
    Second : First - Third -
    Third : Second - Etc -
    Etc : First - Third -
    None :
    None :
    None :
    None :
    None :
    None :
    ------------------------------------------
    - Graph Traversal from FIRST NODE
    First - Second - Etc - Third -
    ------------------------------------------

     

    실행결과_DFS

    ------------------------------------------
    - Class Name            : Graph_AdjacencyMatrix
    - GraphOption           : Undirected
    - GraphTraversal        : DFS
    - Graph Nodes
    Index[0] : First - Index[1] : Second - Index[2] : Third - Index[3] : Etc
    ------------------------------------------
    - Graph Edges
    First : Second - Etc -
    Second : First - Third -
    Third : Second - Etc -
    Etc : First - Third -
    None :
    None :
    None :
    None :
    None :
    None :
    ------------------------------------------
    - Graph Traversal from FIRST NODE
    First - Etc - Third - Second -
    ------------------------------------------

    댓글

Designed by Tistory.