diff --git a/thu_dsa/chp2/Vector.h b/thu_dsa/chp2/Vector.h index 00b4f88..488bfee 100644 --- a/thu_dsa/chp2/Vector.h +++ b/thu_dsa/chp2/Vector.h @@ -34,6 +34,7 @@ public: //constructors Vector(); Vector(int capacity); + Vector(int size, T const &value); Vector(T* const A, int n) { copyfrom(A, 0, n); } Vector(T* const A, int lo, int hi) { copyfrom(A, lo, hi); } Vector(Vector const &V) { copyfrom(V._elem, 0, V._size); } @@ -149,6 +150,15 @@ Vector::Vector(int capacity) { _elem = new T[_capacity]; } +template +Vector::Vector(int size, T const &value){ + _capacity = size << 1; + _size = size; + _elem = new T[_capacity]; + for (int ix = 0; ix != _size; ++ix) + _elem[ix] = value; +} + //read-only interfaces template void Vector::print() { diff --git a/thu_dsa/chp2/testVector.cpp b/thu_dsa/chp2/testVector.cpp index 30d9e1d..9eda077 100644 --- a/thu_dsa/chp2/testVector.cpp +++ b/thu_dsa/chp2/testVector.cpp @@ -66,6 +66,12 @@ void test_constructor() { assert(V5.getSize() == 2); assert(V5.getCapacity() == 4); + Vector V6(10, 0); + assert(V6.getSize() == 10); + assert(V6.getCapacity() == 20); + for (int ix = 0; ix != 10; ++ix) + assert(V6[ix] == 0); + cout << "test passed." << endl; } diff --git a/thu_dsa/chp6/Edge.h b/thu_dsa/chp6/Edge.h index 16df902..4dc6a24 100644 --- a/thu_dsa/chp6/Edge.h +++ b/thu_dsa/chp6/Edge.h @@ -5,10 +5,12 @@ template class Edge{ +public: Te data; double weight = 1; Etype type = UNDETERMINED; + Edge() = default; Edge(Te data) : data(data) {} Edge(Te data, double w) : data(data), weight(w) {} }; diff --git a/thu_dsa/chp6/Graph.h b/thu_dsa/chp6/Graph.h index 36ac2f7..dd03498 100644 --- a/thu_dsa/chp6/Graph.h +++ b/thu_dsa/chp6/Graph.h @@ -8,7 +8,7 @@ typedef enum { UNDISCOVERED, DISCOVERED, VISITED } VStatus; typedef enum { UNDETERMINED, TREE, BACKWARD, FORWARD, CROSS } Etype; //abstract class Graph -template template +template class Graph{ private: void reset(); @@ -38,11 +38,11 @@ public: //directed egde methods virtual bool exists(int, int) = 0; - virtual void insertEdge(Te const&, int, int, int) = 0; + virtual void insertEdge(Te const&, double, int, int) = 0; virtual Te removeEdge(int, int) = 0; virtual Etype& type(int, int) = 0; virtual Te& edge(int, int) = 0; - virtual int& weight(int, int) = 0; + virtual double& weight(int, int) = 0; //Graph related algorithms void bfs(int); diff --git a/thu_dsa/chp6/GraphMatrix.h b/thu_dsa/chp6/GraphMatrix.h index a7399a2..cd4a651 100644 --- a/thu_dsa/chp6/GraphMatrix.h +++ b/thu_dsa/chp6/GraphMatrix.h @@ -6,7 +6,7 @@ #include "Vertex.h" #include "../chp2/Vector.h" -template template +template class GraphMatrix: public Graph{ private: Vector> V; @@ -29,60 +29,83 @@ public: int outDegree(int vertexId) { return V[vertexId].outDegree; } int firstNeighbor(int vertexId); int nextNeighbor(int vertexId, int curr); - int& dtime(int vertexId) { return V[vertexId].dtime; } - int& ftime(int vertexId) { return V[vertexId].ftime; } + int& dtime(int vertexId) { return V[vertexId].dTime; } + int& ftime(int vertexId) { return V[vertexId].fTime; } int& parent(int vertexId) { return V[vertexId].parent; } int& priority(int vertexId) { return V[vertexId].priority; } VStatus& status(int vertexId) { return V[vertexId].status; } //directed edge methods bool exists(int src, int tail) { return E[src][tail] != nullptr; } - void insertEdge(Te const &data, int weight, int src, int tail); + void insertEdge(Te const &data, int src, int tail) { insertEdge(data, 1, src, tail); } + void insertEdge(Te const &data, double weight, int src, int tail); Te removeEdge(int src, int tail); - Etype& type(int src, int tail) { return E[src][tail]->type; } - Te& edge(int src, int tail) { return E[src][tail]->data; } - int& weight(int src, int tail) { return E[src][tail]->weight; } + Etype& type(int src, int tail) { return E[src][tail]->type; } + Te& edge(int src, int tail) { return E[src][tail]->data; } + double& weight(int src, int tail) { return E[src][tail]->weight; } }; +//application interfaces +void graph_demo(GraphMatrix &G); + /*---------------Implementations---------------*/ //constructor -template template +template GraphMatrix::GraphMatrix(){ num_of_vertices = 0; num_of_edges = 0; +} - V = Vector>(); - E = Vector>>(); +//deconstructor +template +GraphMatrix::~GraphMatrix(){ + for (int ix = 0; ix != num_of_vertices; ++ix) + for (int jx = 0; jx != num_of_vertices; ++jx) + if (exists(ix, jx)) delete E[ix][jx]; } //implementations of abstract Graph methods //vertex methods -template template +template int GraphMatrix::insertVertex(Tv const & data){ V.push_back(Vertex(data)); for (int ix = 0; ix != num_of_vertices; ++ix) E[ix].push_back(nullptr); - E.push_back(Vector*>(nullptr, ++num_of_vertices)); + E.push_back(Vector*>(++num_of_vertices, nullptr)); return num_of_vertices - 1; } -template template -Te GraphMatrix::removeVertex(int vertexId){ +template +Tv GraphMatrix::removeVertex(int vertexId){ + for (int ix = 0; ix != num_of_vertices; ++ix) + if (exists(vertexId, ix)) removeEdge(vertexId, ix); + for (int ix = 0; ix != num_of_vertices; ++ix) { - //remove edges - if(exists(ix, vertexId) removeEdge(ix, vertexId); - if(exists(vertexId, ix) removeEdge(vertexId, ix); + if(exists(ix, vertexId)) removeEdge(ix, vertexId); E[ix].pop(vertexId); } E.pop(vertexId); - --num_of_vertices; + num_of_vertices--; return V.pop(vertexId).data; } +template +int GraphMatrix::firstNeighbor(int vertexId) { + return nextNeighbor(vertexId, num_of_vertices); +} + +template +int GraphMatrix::nextNeighbor(int vertexId, int curr) { + while(0 <= --curr){ + if (exists(vertexId, curr)) break; + } + return curr; +} + //edge methods -template template -void GraphMatrix::insertEdge(Te const &data, int weight, int src, int tail){ +template +void GraphMatrix::insertEdge(Te const &data, double weight, int src, int tail){ if (src < 0 || src >= num_of_vertices || tail < 0 || tail >= num_of_vertices) return; if (exists(src, tail)) return; @@ -90,14 +113,14 @@ void GraphMatrix::insertEdge(Te const &data, int weight, int src, int ta ++num_of_edges; V[tail].inDegree++; - V[src].outDegree--; + V[src].outDegree++; } -template template +template Te GraphMatrix::removeEdge(int src, int tail){ Te edgeBak = edge(src, tail); - delete edge(src, tail); - edge(src, tail) = nullptr; + delete E[src][tail]; + E[src][tail] = nullptr; --num_of_edges; V[tail].inDegree--; @@ -105,4 +128,20 @@ Te GraphMatrix::removeEdge(int src, int tail){ return edgeBak; } +//application interfaces +void graph_demo(GraphMatrix &G) { + G = GraphMatrix(); + char *alphabet = "abcdefghij"; + for (int ix = 0; ix != 10; ++ix) + G.insertVertex(alphabet[ix]); + G.insertEdge(1, 0, 1); + G.insertEdge(1, 0, 7); + G.insertEdge(1, 4, 2); + G.insertEdge(1, 5, 4); + G.insertEdge(1, 5, 3); + G.insertEdge(1, 6, 7); + G.insertEdge(1, 9, 6); + G.insertEdge(1, 3, 8); +} + #endif diff --git a/thu_dsa/chp6/Vertex.h b/thu_dsa/chp6/Vertex.h index b3e024d..dce10ff 100644 --- a/thu_dsa/chp6/Vertex.h +++ b/thu_dsa/chp6/Vertex.h @@ -15,6 +15,7 @@ public: int inDegree = 0; int outDegree = 0; + Vertex() = default; Vertex(Tv data) : data(data) {} }; diff --git a/thu_dsa/chp6/testGraphMatrix.cpp b/thu_dsa/chp6/testGraphMatrix.cpp new file mode 100644 index 0000000..5cf8f6c --- /dev/null +++ b/thu_dsa/chp6/testGraphMatrix.cpp @@ -0,0 +1,148 @@ +#include "GraphMatrix.h" +#include +#include +using std::cout; +using std::endl; + +void test_constructor(); +void test_vertex_insert(); +void test_vertex_delete(); +void test_edge_insert(); + +int main(){ + cout << "Running tests" << endl; + + test_constructor(); + test_vertex_insert(); + test_edge_insert(); + test_vertex_delete(); + + cout << "All tests passed." << endl; + system("pause"); + return 0; +} + +void test_constructor(){ + GraphMatrix G; + assert(G.num_of_edges == 0); + assert(G.num_of_vertices == 0); +} + +void test_vertex_insert(){ + GraphMatrix G; + G.insertVertex('a'); + assert(G.num_of_vertices == 1); + assert(G.num_of_edges == 0); + assert(G.exists(0, 0) == false); + assert(G.vertex(0) == 'a'); + assert(G.inDegree(0) == 0); + assert(G.outDegree(0) == 0); + assert(G.priority(0) == 0); + assert(G.dtime(0) == -1); + assert(G.ftime(0) == -1); + assert(G.parent(0) == -1); + + G.insertVertex('b'); + assert(G.num_of_vertices == 2); + assert(G.num_of_edges == 0); + assert(G.exists(0, 1) == false); + assert(G.exists(1, 1) == false); + assert(G.vertex(1) == 'b'); +} + +void test_edge_insert(){ + GraphMatrix G; + graph_demo(G); + + assert(G.num_of_edges == 8); + assert(G.edge(0, 1) == 1); + assert(G.weight(0, 1) == 1.); + assert(G.type(0, 1) == UNDETERMINED); + assert(G.exists(0, 7)); + assert(G.exists(4, 2)); + assert(G.exists(5, 4)); + assert(G.exists(5, 3)); + assert(G.exists(6, 7)); + assert(G.exists(9, 6)); + assert(G.exists(3, 8)); + + assert(!G.exists(1, 0)); + assert(!G.exists(7, 0)); + assert(!G.exists(2, 4)); + assert(!G.exists(4, 5)); + assert(!G.exists(3, 5)); + assert(!G.exists(7, 6)); + assert(!G.exists(6, 9)); + assert(!G.exists(8, 3)); + + assert(G.inDegree(0) == 0); + assert(G.inDegree(1) == 1); + assert(G.inDegree(2) == 1); + assert(G.inDegree(3) == 1); + assert(G.inDegree(4) == 1); + assert(G.inDegree(5) == 0); + assert(G.inDegree(6) == 1); + assert(G.inDegree(7) == 2); + assert(G.inDegree(8) == 1); + assert(G.inDegree(9) == 0); + + assert(G.outDegree(0) == 2); + assert(G.outDegree(1) == 0); + assert(G.outDegree(2) == 0); + assert(G.outDegree(3) == 1); + assert(G.outDegree(4) == 1); + assert(G.outDegree(5) == 2); + assert(G.outDegree(6) == 1); + assert(G.outDegree(7) == 0); + assert(G.outDegree(8) == 0); + assert(G.outDegree(9) == 1); +} + +void test_vertex_delete(){ + GraphMatrix G; + graph_demo(G); + + G.removeVertex(0); + assert(G.num_of_vertices == 9); + assert(G.num_of_edges == 6); + assert(G.inDegree(0) == 0); + assert(G.inDegree(1) == 1); + assert(G.inDegree(2) == 1); + assert(G.inDegree(3) == 1); + assert(G.inDegree(4) == 0); + assert(G.inDegree(5) == 1); + assert(G.inDegree(6) == 1); + assert(G.inDegree(7) == 1); + assert(G.inDegree(8) == 0); + + assert(G.outDegree(0) == 0); + assert(G.outDegree(1) == 0); + assert(G.outDegree(2) == 1); + assert(G.outDegree(3) == 1); + assert(G.outDegree(4) == 2); + assert(G.outDegree(5) == 1); + assert(G.outDegree(6) == 0); + assert(G.outDegree(7) == 0); + assert(G.outDegree(8) == 1); + + G.removeVertex(5); + assert(G.num_of_vertices == 8); + assert(G.num_of_edges == 4); + assert(G.inDegree(0) == 0); + assert(G.inDegree(1) == 1); + assert(G.inDegree(2) == 1); + assert(G.inDegree(3) == 1); + assert(G.inDegree(4) == 0); + assert(G.inDegree(5) == 0); + assert(G.inDegree(6) == 1); + assert(G.inDegree(7) == 0); + + assert(G.outDegree(0) == 0); + assert(G.outDegree(1) == 0); + assert(G.outDegree(2) == 1); + assert(G.outDegree(3) == 1); + assert(G.outDegree(4) == 2); + assert(G.outDegree(5) == 0); + assert(G.outDegree(6) == 0); + assert(G.outDegree(7) == 0); +}