-
알고리즘...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 - ------------------------------------------