279 lines
11 KiB
C++
279 lines
11 KiB
C++
#include "extendedgraph.h"
|
|
#include <map>
|
|
|
|
ExtendedGraph::ExtendedGraph() { // Default Constructor
|
|
this->vertices =
|
|
std::vector<std::string>(0); // Empty Vector for this->vertices
|
|
this->adjacencyMatrix.resize(
|
|
0, std::vector<int>(0)); // 0x0 Matrix for this->adjacencyMatrix
|
|
}
|
|
|
|
/* --
|
|
Constructor with params
|
|
-- */
|
|
ExtendedGraph::ExtendedGraph(const std::vector<std::string> &vertices,
|
|
const std::vector<Edge> &edges) {
|
|
this->vertices = vertices; // definition of this->vertex through parameter
|
|
// vertices (type: std::vector<std::string>)
|
|
this->adjacencyMatrix.resize(
|
|
vertices.size(),
|
|
std::vector<int>(
|
|
this->vertices.size())); // creation of an NxN Matrix, based on the
|
|
// size of vertices
|
|
|
|
for (int i = 0; i < edges.size(); i++) {
|
|
insertEdge(edges[i]); // edges are added one by one, utilizing the
|
|
// insertEdge()-Function
|
|
}
|
|
}
|
|
|
|
/* -- /
|
|
Function to insert a vertex into the Graph;
|
|
- takes one argument of type std::string that represents a vertex
|
|
- returns void
|
|
/ -- */
|
|
void ExtendedGraph::insertVertex(const std::string &vertex) {
|
|
if (this->resolveVertex(vertex) != -1) { /* -- */
|
|
std::cerr
|
|
<< "Vertex already in Graph!\n"; /* Calls this->resolveVertex to check
|
|
if a given vertex is already in the
|
|
Graph. Returns with an error, if
|
|
this is the case. */
|
|
return; /* -- */
|
|
}
|
|
this->vertices.push_back(vertex); // adds a vertetx via the push_back
|
|
// function provided by std::vector
|
|
this->adjacencyMatrix.resize(
|
|
this->vertices.size(),
|
|
std::vector<int>(this->vertices.size())); // resizes the adjacencyMatrix
|
|
// to the new size
|
|
for (int i = 0; i < this->vertices.size(); i++) { /* -- */
|
|
adjacencyMatrix[i].resize(
|
|
this->vertices.size()); /* resizes every "sub" vector of the matrix to
|
|
the new size */
|
|
} /* -- */
|
|
}
|
|
|
|
/* -- /
|
|
Function to delete a vertex from the Graph;
|
|
- takes one argument of type std::string that represents a vertex
|
|
- returns void
|
|
/ -- */
|
|
void ExtendedGraph::deleteVertex(const std::string &vertex) {
|
|
int index = this->resolveVertex(vertex);
|
|
if (index == -1) { /* -- */
|
|
std::cerr << "Vertex not found\n"; /* Calls this->resolveVertex to check if
|
|
a given vertex is already in the
|
|
Graph. Returns with an error, if this
|
|
is the case. */
|
|
return; /* -- */
|
|
}
|
|
this->vertices.erase(
|
|
this->vertices.begin() +
|
|
index); // erases the vertex at position "index" from this->vertices
|
|
|
|
this->adjacencyMatrix.erase(
|
|
this->adjacencyMatrix.begin() +
|
|
index); // erases the entries from the adjacencyMatrix at "column"
|
|
// position "index"
|
|
for (int i = 0; i < this->adjacencyMatrix[0].size(); i++) { /* -- */
|
|
this->adjacencyMatrix[i].erase(this->adjacencyMatrix[i].begin() +
|
|
index); /* erases the entries from the
|
|
adjacencyMatrix in every "row" */
|
|
} /* -- */
|
|
}
|
|
|
|
/* -- /
|
|
Function to insert an Edge
|
|
- takes one argument of type Edge that represents an edge
|
|
- returns void
|
|
/ -- */
|
|
void ExtendedGraph::insertEdge(const Edge &edge) {
|
|
int col = this->resolveVertex(
|
|
edge.getSrc()); // resolves the src of the edge to the index within the
|
|
// adjacencyMatrix
|
|
int row = this->resolveVertex(
|
|
edge.getDest()); // resolves the dest of the edge to the index within the
|
|
// adjacencyMatrix
|
|
if (col == -1 || row == -1) { /* -- */
|
|
std::cerr << "Vertex not found!\n"; /* Calls this->resolveVertex to check
|
|
if a given vertex is already in the
|
|
Graph. Returns with an error, if this
|
|
is the case. */
|
|
return; /* -- */
|
|
}
|
|
|
|
this->adjacencyMatrix[col][row] =
|
|
edge.getWeight(); // sets the value of the adjacencyMatrix at position
|
|
// [col][row] to the weight of the edge
|
|
}
|
|
|
|
/* -- /
|
|
Function to delete an Edge
|
|
- takes one argument of type Edge that represents an edge
|
|
- returns void
|
|
/ -- */
|
|
void ExtendedGraph::deleteEdge(const Edge &edge) {
|
|
int col = this->resolveVertex(
|
|
edge.getSrc()); // resolves the src of the edge to the index within the
|
|
// adjacencyMatrix
|
|
int row = this->resolveVertex(
|
|
edge.getDest()); // resolves the dest of the edge to the index within the
|
|
// adjacencyMatrix
|
|
if (col == -1 || row == -1) { /* -- */
|
|
std::cerr << "Vertex not found!\n"; /* Calls this->resolveVertex to check
|
|
if a given vertex is already in the
|
|
Graph. Returns with an error, if this
|
|
is the case. */
|
|
return; /* -- */
|
|
}
|
|
this->adjacencyMatrix[col][row] =
|
|
0; // sets the value of the adjacencyMatrix at position [col][row] to 0
|
|
}
|
|
|
|
/* -- /
|
|
Function to check whether vertex v2 is adjacent to vertex v1
|
|
- takes one argument of type Edge that represents an edge
|
|
- returns void
|
|
/ -- */
|
|
bool ExtendedGraph::adjacent(const std::string &vertex1,
|
|
const std::string &vertex2) {
|
|
int indexVertex1 = this->resolveVertex(vertex1);
|
|
int indexVertex2 = this->resolveVertex(vertex2);
|
|
if (indexVertex1 == -1 || indexVertex2 == -1) {
|
|
std::cerr << "Vertex not found!\n";
|
|
return false;
|
|
}
|
|
// As adjacency is an equivalency relation, we need to check for a possible
|
|
// relation in both direction. This can be achieved by swapping the the
|
|
// position specifications of the adjacencyMatrix (from
|
|
// [indexVertex1][indexVertex2] to [indexVertex2][indexVertex1]).
|
|
if (this->adjacencyMatrix[indexVertex1][indexVertex2] != 0 ||
|
|
this->adjacencyMatrix[indexVertex2][indexVertex1] != 0) {
|
|
return true; // if a connection (in any direction) is found, return true
|
|
} else {
|
|
return false; // else, return false
|
|
}
|
|
}
|
|
|
|
/* -- /
|
|
Function that returns an std::vector of std::string representing the
|
|
neighbouring vertices of the parameter std::string vertex. Other than adjacent,
|
|
neighbourhood is a directed relationship, which means that a vertex "A" can be
|
|
the neighbour of "B", but this does not automatically imply that "B" is the
|
|
neighbour of "A".
|
|
- takes one argument of type std::string that represents a vertex
|
|
- returns a std::vector of std::string
|
|
/ -- */
|
|
std::vector<std::string> ExtendedGraph::neighbours(const std::string &vertex) {
|
|
int indexVertex = this->resolveVertex(
|
|
vertex); // resolves the vertex to the index within the adjacencyMatrix
|
|
std::vector<std::string> resVector =
|
|
{}; // initializes an empty std::vetor of std::string
|
|
for (int i = 0; i < this->adjacencyMatrix[indexVertex].size();
|
|
i++) { /* Loops through all entries of the subvector of
|
|
adjacencyMatrix[indexVertex] */
|
|
if (this->adjacencyMatrix[indexVertex][i] !=
|
|
0) { /* and checks if the entry at position [indexVertex][i] is not 0.
|
|
*/
|
|
resVector.push_back(
|
|
this->vertices[i]); /* If the condition is fulfilled, add the vertex
|
|
(name) to the result vector resVector */
|
|
}
|
|
}
|
|
return resVector;
|
|
}
|
|
|
|
/* -- /
|
|
Function that prints the current Graph's adjacencyMatrix.
|
|
- prints the Graph by utilizing std::cout
|
|
- returns void
|
|
/ -- */
|
|
void ExtendedGraph::printGraph() {
|
|
std::cout << "--------------------------------------------\n";
|
|
std::cout << "\t\t\t";
|
|
for (int i = 0; i < this->vertices.size(); i++) {
|
|
std::cout << this->vertices[i] << "\t";
|
|
}
|
|
std::cout << "\n";
|
|
for (int i = 0; i < this->vertices.size(); i++) {
|
|
std::cout << " " << this->vertices[i] << "\t\t-->\t";
|
|
for (int j = 0; j < this->vertices.size(); j++) {
|
|
std::cout << this->adjacencyMatrix[i][j] << "\t";
|
|
}
|
|
std::cout << "\n";
|
|
}
|
|
std::cout << "--------------------------------------------\n";
|
|
};
|
|
|
|
/* -- /
|
|
Function that resolves a parameter std::string name and returns it's index
|
|
within the this->vertices vector; between vertices of type std::string and the
|
|
corresponding index (in the adjacencyMatrix) of type int.
|
|
- takes one argument of type std::string that represents a vertex
|
|
- returns an int representing the vertex's index in the adjacencyMatrix;
|
|
- function returns -1 in case the resolution of the name is unsuccessful
|
|
/ -- */
|
|
int ExtendedGraph::resolveVertex(const std::string &vertexName) {
|
|
for (int i = 0; i < this->vertices.size(); i++) {
|
|
if (this->vertices[i] == vertexName) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int ExtendedGraph::minDistance(int dist[], bool sptSet[]) {
|
|
int min = INT_MAX, min_index;
|
|
|
|
for (int v = 0; v < this->vertices.size(); v++)
|
|
if (sptSet[v] == false && dist[v] <= min)
|
|
min = dist[v], min_index = v;
|
|
|
|
return min_index;
|
|
}
|
|
|
|
void ExtendedGraph::performDijkstraPath(std::string sourceVertex,
|
|
std::string targetVertex) {
|
|
int dist[this->vertices.size()];
|
|
bool sptSet[vertices.size()];
|
|
int parent[vertices.size()];
|
|
for (int i = 0; i < vertices.size(); i++) {
|
|
parent[i] = -1;
|
|
}
|
|
|
|
for (int i = 0; i < this->vertices.size(); i++) {
|
|
dist[i] = INT_MAX;
|
|
sptSet[i] = false;
|
|
}
|
|
dist[resolveVertex(sourceVertex)] = 0;
|
|
for (int count = 0; count < this->vertices.size() - 1; count++) {
|
|
int m = minDistance(dist, sptSet);
|
|
sptSet[m] = true;
|
|
for (int v = 0; v < vertices.size(); v++) {
|
|
if (!sptSet[v] && this->adjacencyMatrix[m][v] && dist[m] != INT_MAX &&
|
|
dist[m] + this->adjacencyMatrix[m][v] < dist[v]) {
|
|
dist[v] = dist[m] + this->adjacencyMatrix[m][v];
|
|
parent[v] = m;
|
|
}
|
|
}
|
|
if (sptSet[resolveVertex(targetVertex)]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::cout << sourceVertex << " ";
|
|
int sumPath = 0;
|
|
printPath(parent, resolveVertex(targetVertex), dist, sumPath);
|
|
std::cout << "; Gesamter Zollbetrag: " << sumPath << std::endl;
|
|
}
|
|
|
|
void ExtendedGraph::printPath(int parent[], int j, int dist[], int &sum) {
|
|
// Base Case : If j is source
|
|
if (parent[j] == -1)
|
|
return;
|
|
printPath(parent, parent[j], dist, sum);
|
|
std::cout << " -(" << this->adjacencyMatrix[parent[j]][j] << ")-> "
|
|
<< this->vertices[j] << std::flush;
|
|
sum += adjacencyMatrix[parent[j]][j];
|
|
} |