#ifndef MATRIXGRAPH_H #define MATRIXGRAPH_H #include "DynamicArray.h" #include "Exception.h" #include "Graph.h" namespace Kylin { /** * MatrixGraph row即为起始点Vertex的index,col即为终止点的index */ template class MatrixGraph : public Graph { public: VertexType vertex(size_t index) const final { if (index >= vertexCount()) THROW_EXCEPTION(IndexOutOfBoundsException, "Index is out of bounds."); if (m_vetexes[index] != nullptr) { return *(m_vetexes[index]); } else { THROW_EXCEPTION(InvalidOperationException, "No value assigned to this vertex."); } } bool setVertex(size_t index, const VertexType &value) final { bool ret = ((0 <= index) && (index < vertexCount())); if (!ret) return false; auto data = m_vetexes[index]; if (data == nullptr) data = new VertexType(); if (data != nullptr) { *data = value; m_vetexes[index] = data; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No memory to store new vertex value ..."); } return ret; } /** * @brief 获取与Vertex[index]相邻接的顶点(Vertex[index]作为起始点) */ DynamicArray adjacent(size_t index) const final { if ((0 <= index) && (index < vertexCount())) { size_t n = 0; for (size_t j = 0; j < vertexCount(); j++) { if (m_edges[index][j] != nullptr) { n++; } } DynamicArray ret(n); for (size_t j = 0, k = 0; j < vertexCount(); j++) { if (m_edges[index][j] != nullptr) ret[k++] = j; } return ret; } else { THROW_EXCEPTION(InvalidParameterException, "Index is invalid..."); } } std::optional edge(size_t start, size_t end) const final { bool status = ((0 <= start) && (start < vertexCount())) && ((0 <= end) && (end < vertexCount())); if (!status) return std::optional{}; if (m_edges[start][end] != nullptr) { return std::optional{*(m_edges[start][end])}; } else { return std::optional{}; } } bool setEdge(size_t start, size_t end, const EdgeType &value) final { bool ret = ((0 <= start) && (start < vertexCount())) && ((0 <= end) && (end < vertexCount())); if (!ret) return false; auto ne = m_edges[start][end]; if (ne == nullptr) { ne = new EdgeType(); if (ne != nullptr) { *ne = value; m_edges[start][end] = ne; m_edgeCount++; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No memory to store new edge value ..."); } } else { *ne = value; } return ret; } bool removeEdge(size_t start, size_t end) final { bool ret = ((0 <= start) && (start < vertexCount())) && ((0 <= end) && (end < vertexCount())); if (!ret) return false; auto toDel = m_edges[start][end]; m_edges[start][end] = nullptr; if (toDel != nullptr) { m_edgeCount--; delete toDel; } return ret; } size_t vertexCount() const final { return N; } size_t edgeCount() const final { return m_edgeCount; } size_t outDegree(size_t index) const final { size_t ret = 0; if ((0 <= index) && (index < vertexCount())) { for (size_t j = 0; j < vertexCount(); j++) { if (m_edges[index][j] != nullptr) ret++; } } else { THROW_EXCEPTION(InvalidParameterException, "Index i is invalid ..."); } return ret; } size_t inDegree(size_t index) const final { size_t ret = 0; if ((0 <= index) && (index < vertexCount())) { for (size_t i = 0; i < vertexCount(); i++) { if (m_edges[i][index] != nullptr) ret++; } } else { THROW_EXCEPTION(InvalidParameterException, "Index j is invalid ..."); } return ret; } ~MatrixGraph() { auto vetexes = vertexCount(); for (size_t i = 0; i < vetexes; i++) { for (size_t j = 0; j < vetexes; j++) { delete m_edges[i][j]; } delete m_vetexes[i]; } } protected: VertexType *m_vetexes[N] = {nullptr}; EdgeType *m_edges[N][N] = {nullptr}; size_t m_edgeCount = 0; }; } // namespace Kylin #endif // MATRIXGRAPH_H