Kylin/DataStructure/MatrixGraph.h
2023-12-27 10:29:16 +08:00

146 lines
4.8 KiB
C++

#ifndef MATRIXGRAPH_H
#define MATRIXGRAPH_H
#include "DynamicArray.h"
#include "Exception.h"
#include "Graph.h"
namespace Kylin {
/**
* MatrixGraph row即为起始点Vertex的index,col即为终止点的index
*/
template <int N, typename VertexType, typename EdgeType>
class MatrixGraph : public Graph<VertexType, EdgeType> {
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<size_t> 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<size_t> 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<EdgeType> edge(size_t start, size_t end) const final {
bool status = ((0 <= start) && (start < vertexCount())) && ((0 <= end) && (end < vertexCount()));
if (!status) return std::optional<EdgeType>{};
if (m_edges[start][end] != nullptr) {
return std::optional<EdgeType>{*(m_edges[start][end])};
} else {
return std::optional<EdgeType>{};
}
}
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