mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
356 lines
6.9 KiB
C++
356 lines
6.9 KiB
C++
|
|
|
|
|
|
#include <iostream>
|
|
#include <queue>
|
|
#include "graph.h"
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
Graph::Graph(int newMaxSize)
|
|
: mInvalid()
|
|
{
|
|
maxSize = newMaxSize;
|
|
// vertexList = new Vertex [maxSize];
|
|
}
|
|
|
|
|
|
Graph::Graph(const Graph& other)
|
|
{
|
|
*this = other;
|
|
}
|
|
|
|
|
|
Graph& Graph::operator=(const Graph& other)
|
|
{
|
|
if (this == &other)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
if (!empty())
|
|
{
|
|
vertexList.clear();
|
|
}
|
|
|
|
maxSize = other.maxSize;
|
|
vertexList.assign(other.vertexList.begin(), other.vertexList.end());
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
Graph::~Graph()
|
|
{
|
|
// delete[] vertexList;
|
|
vertexList.clear();
|
|
}
|
|
|
|
|
|
bool Graph::addVertex(const string& id)
|
|
{
|
|
if (full())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Vertex newVertex;
|
|
newVertex.setId(id);
|
|
vertexList.push_back(newVertex);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void Graph::insertEdge(const string& v1, const string& v2, int wt)
|
|
{
|
|
std::list<Vertex>::iterator it_v1 = vertexList.end();
|
|
std::list<Vertex>::iterator it_v2 = vertexList.end();
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if (it->getId() == v1)
|
|
{
|
|
it_v1 = it;
|
|
}
|
|
if (it->getId() == v2)
|
|
{
|
|
it_v2 = it;
|
|
}
|
|
}
|
|
|
|
if ((it_v1 != vertexList.end()) && (it_v2 != vertexList.end()))
|
|
{
|
|
if (wt == -1)
|
|
{
|
|
wt = it_v1->first_edge_gap();
|
|
}
|
|
it_v1->edges.push_back(make_pair(wt, *it_v2));
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Cannot create edge, one vertex is not found" << std::endl;
|
|
}
|
|
}
|
|
|
|
Graph::Vertex Graph::first() const
|
|
{
|
|
if (vertexList.size() > 0) {
|
|
return vertexList.front();
|
|
} else {
|
|
return Vertex();
|
|
}
|
|
}
|
|
|
|
Graph::Vertex Graph::getVertex(const string &v) const
|
|
{
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if (it->getId() == v)
|
|
{
|
|
return *it;
|
|
}
|
|
}
|
|
return mInvalid;
|
|
}
|
|
|
|
Graph::Vertex Graph::getPreviousVertex(const string &id)
|
|
{
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if (it->edges.size() > 0)
|
|
{
|
|
Vertex v = it->edges.front().second;
|
|
if (v.getId() == id)
|
|
{
|
|
return *it;
|
|
}
|
|
}
|
|
}
|
|
return mInvalid;
|
|
}
|
|
|
|
Graph::Vertex Graph::getNextVertex(const std::string &id) const
|
|
{
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if ((it->getId() == id))
|
|
{
|
|
if (it->edges.size() > 0)
|
|
{
|
|
return it->edges.front().second;
|
|
}
|
|
}
|
|
}
|
|
return mInvalid;
|
|
}
|
|
|
|
|
|
void Graph::Vertex::removeEdge(const std::string &id)
|
|
{
|
|
edges.remove_if([id](const vPair &n){ return (n.second.getId() == id); });
|
|
}
|
|
|
|
bool Graph::removeVertex(const string& v)
|
|
{
|
|
std::list<Vertex>::iterator it_v = vertexList.end();
|
|
|
|
// On cherche le vertex
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if (it->getId() == v)
|
|
{
|
|
it_v = it;
|
|
}
|
|
}
|
|
|
|
// vertex non trouvé
|
|
if (it_v == vertexList.end())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::cout << "RM: " << it_v->getId()<< std::endl;
|
|
vertexList.erase(it_v);
|
|
|
|
// On supprime toutes les références à ce vertex dans les autres edges
|
|
// == On supprime les relations éventuelles
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
it->removeEdge(v);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Graph::removeEdge(const string& v1, const string& v2)
|
|
{
|
|
bool success = false;
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if (it->getId() == v1)
|
|
{
|
|
success = true;
|
|
it->removeEdge(v2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
bool Graph::clearExtraEdges(const std::string &v1)
|
|
{
|
|
bool success = false;
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
if (it->getId() == v1)
|
|
{
|
|
success = true;
|
|
it->edges.remove_if([](const Vertex::vPair &n){ return (n.first != 0); });
|
|
break;
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
void Graph::clear()
|
|
{
|
|
vertexList.clear();
|
|
}
|
|
|
|
|
|
bool Graph::empty() const
|
|
{
|
|
return (vertexList.size() == 0);
|
|
}
|
|
|
|
|
|
bool Graph::full() const
|
|
{
|
|
return (vertexList.size() == maxSize);
|
|
}
|
|
|
|
|
|
void Graph::showGraph() const
|
|
{
|
|
if (empty())
|
|
{
|
|
cout << "Empty Graph" << endl;
|
|
return;
|
|
}
|
|
|
|
cout << "Vertex and their adjacency list:" << endl;
|
|
for (auto it = vertexList.begin(); it != vertexList.end(); ++it)
|
|
{
|
|
cout << '\t' << it->getId();
|
|
|
|
for (const auto &j : it->edges)
|
|
{
|
|
cout << " --> [" << j.second.getId()
|
|
<< ", " << j.first << ']';
|
|
}
|
|
cout << endl;
|
|
}
|
|
}
|
|
/*
|
|
|
|
void Graph::bfs(const string& src, const string& dest) const
|
|
{
|
|
int src_idx = getIndex(src),
|
|
dest_idx = getIndex(dest);
|
|
|
|
if (src_idx == -1 ||
|
|
dest_idx == -1)
|
|
return;
|
|
|
|
queue<int> q;
|
|
vector<bool> visited(size, false);
|
|
|
|
q.push(src_idx);
|
|
visited[src_idx] = true;
|
|
|
|
while (!q.empty())
|
|
{
|
|
int u = q.front();
|
|
q.pop();
|
|
|
|
cout << ' ' << vertexList[u].getId() << endl;
|
|
|
|
if (u == dest_idx)
|
|
return;
|
|
|
|
for (auto i : vertexList[u].edges)
|
|
{
|
|
int v = getIndex(i.second.getId());
|
|
|
|
if (!visited[v])
|
|
{
|
|
visited[v] = true;
|
|
q.push(v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Graph::shortestPaths(const string& src) const
|
|
{
|
|
typedef pair<int,int> vtx;
|
|
priority_queue<vtx,
|
|
vector<vtx>,
|
|
greater<vtx> > pq;
|
|
|
|
vector<int> dist(size, INF);
|
|
|
|
int src_idx = getIndex(src);
|
|
if (src_idx == -1) return;
|
|
|
|
dist[src_idx] = 0;
|
|
pq.push(make_pair(0, src_idx));
|
|
|
|
while (!pq.empty())
|
|
{
|
|
int u = pq.top().second;
|
|
pq.pop();
|
|
|
|
for (auto i : vertexList[u].edges)
|
|
{
|
|
int v = getIndex(i.second.getId());
|
|
int wt = i.first;
|
|
|
|
if (dist[v] > dist[u] + wt)
|
|
{
|
|
dist[v] = dist[u] + wt;
|
|
pq.push(make_pair(dist[v], v));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
cout << '\t' << vertexList[i].getId();
|
|
if (dist[i] == INF)
|
|
cout << '\t' << '-' << endl;
|
|
else
|
|
cout << '\t' << dist[i] << endl;
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
|
|
int Graph::getIndex(const string& v) const
|
|
{
|
|
for (int i = 0; i < size; i++)
|
|
if (v == vertexList[i].getId())
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
*/
|
|
|