Skip to content

Instantly share code, notes, and snippets.

@luistelmocosta
Created April 12, 2016 14:18
Show Gist options
  • Save luistelmocosta/6c19785fb11e3689d4a121a8ab174789 to your computer and use it in GitHub Desktop.
Save luistelmocosta/6c19785fb11e3689d4a121a8ab174789 to your computer and use it in GitHub Desktop.
/*
* Graph.h
*/
#ifndef GRAPH_H_
#define GRAPH_H_
#include <vector>
#include <queue>
#include <list>
#include <climits>
#include <cmath>
#include <stddef.h>
using namespace std;
template <class T> class Edge;
template <class T> class Graph;
const int NOT_VISITED = 0;
const int BEING_VISITED = 1;
const int DONE_VISITED = 2;
const int INT_INFINITY = INT_MAX;
/*
* ================================================================================================
* Class Vertex
* ================================================================================================
*/
template <class T>
class Vertex {
T info;
vector<Edge<T> > adj;
bool visited;
bool processing;
int indegree;
int dist;
public:
Vertex(T in);
friend class Graph<T>;
void addEdge(Vertex<T> *dest, double distance, int line);
bool removeEdgeTo(Vertex<T> *d);
T getInfo() const;
T*getInfoPointer(){
return &info;
}
void setInfo(T info);
int getDist() const;
int getIndegree() const;
int getAdjSize(){
return adj.size();
}
Vertex* path;
};
template <class T>
struct vertex_greater_than {
bool operator()(Vertex<T> * a, Vertex<T> * b) const {
return a->getDist() > b->getDist();
}
};
template <class T>
bool Vertex<T>::removeEdgeTo(Vertex<T> *d) {
d->indegree--; //adicionado do exercicio 5
typename vector<Edge<T> >::iterator it= adj.begin();
typename vector<Edge<T> >::iterator ite= adj.end();
while (it!=ite) {
if (it->dest == d) {
adj.erase(it);
return true;
}
else it++;
}
return false;
}
//atualizado pelo exercício 5
template <class T>
Vertex<T>::Vertex(T in): info(in), visited(false), processing(false), indegree(0), dist(0) {
path = NULL;
}
template <class T>
void Vertex<T>::addEdge(Vertex<T> *dest, double distance, int line) {
Edge<T> edgeD(dest, distance, line);
adj.push_back(edgeD);
}
template <class T>
T Vertex<T>::getInfo() const {
return this->info;
}
template <class T>
int Vertex<T>::getDist() const {
return this->dist;
}
template <class T>
void Vertex<T>::setInfo(T info) {
this->info = info;
}
template <class T>
int Vertex<T>::getIndegree() const {
return this->indegree;
}
/* ================================================================================================
* Class Edge
* ================================================================================================
*/
template <class T>
class Edge {
Vertex<T> * dest;
double distance;
int line;
public:
Edge(Vertex<T> *d, double dis, int l);
friend class Graph<T>;
friend class Vertex<T>;
};
template <class T>
Edge<T>::Edge(Vertex<T> *d, double dis, int l){
dest = d;
distance = dis;
line = l;
}
/* ================================================================================================
* Class Graph
* ================================================================================================
*/
template <class T>
class Graph {
vector<Vertex<T> *> vertexSet;
void dfs(Vertex<T> *v, vector<T> &res) const;
//exercicio 5
int numCycles;
void dfsVisit(Vertex<T> *v);
void dfsVisit();
void getPathTo(Vertex<T> *origin, list<T> &res);
public:
bool addVertex(const T &in);
bool addEdge(const T &sourc, const T &dest, double dis, int line);
bool removeVertex(const T &in);
bool removeEdge(const T &sourc, const T &dest);
vector<T> dfs() const;
vector<T> bfs(Vertex<T> *v) const;
int maxNewChildren(Vertex<T> *v, T &inf) const;
vector<Vertex<T> * > getVertexSet() const;
int getNumVertex() const;
vector<Vertex<T>*> bestPathFrom(const T &s);
void dijkstraShortestPath(const T &s);
//exercicio 5
Vertex<T>* getVertex(const T &v) const;
void resetIndegrees();
vector<Vertex<T>*> getSources() const;
int getNumCycles();
vector<T> topologicalOrder();
vector<T> getPath(const T &origin, const T &dest);
void unweightedShortestPath(const T &v);
bool isDAG();
T getVertexbyId(int id);
T*getVertexbyIdPointer(int id);
int getFirstId(string nome){
for(int i = 0; i < vertexSet.size(); i++){
if(vertexSet[i]->getInfo().getNome() == nome && vertexSet[i]->getInfo().getId() >= 0){
return vertexSet[i]->getInfo().getId();
}
}
return -1;
}
};
template <class T>
int Graph<T>::getNumVertex() const {
return vertexSet.size();
}
template <class T>
vector<Vertex<T> * > Graph<T>::getVertexSet() const {
return vertexSet;
}
template <class T>
int Graph<T>::getNumCycles() {
numCycles = 0;
dfsVisit();
return this->numCycles;
}
template <class T>
bool Graph<T>::isDAG() {
return (getNumCycles() == 0);
}
template <class T>
bool Graph<T>::addVertex(const T &in) {
typename vector<Vertex<T>*>::iterator it= vertexSet.begin();
typename vector<Vertex<T>*>::iterator ite= vertexSet.end();
for (; it!=ite; it++)
if ((*it)->info == in) return false;
Vertex<T> *v1 = new Vertex<T>(in);
vertexSet.push_back(v1);
return true;
}
template <class T>
bool Graph<T>::removeVertex(const T &in) {
typename vector<Vertex<T>*>::iterator it= vertexSet.begin();
typename vector<Vertex<T>*>::iterator ite= vertexSet.end();
for (; it!=ite; it++) {
if ((*it)->info == in) {
Vertex<T> * v= *it;
vertexSet.erase(it);
typename vector<Vertex<T>*>::iterator it1= vertexSet.begin();
typename vector<Vertex<T>*>::iterator it1e= vertexSet.end();
for (; it1!=it1e; it1++) {
(*it1)->removeEdgeTo(v);
}
typename vector<Edge<T> >::iterator itAdj= v->adj.begin();
typename vector<Edge<T> >::iterator itAdje= v->adj.end();
for (; itAdj!=itAdje; itAdj++) {
itAdj->dest->indegree--;
}
delete v;
return true;
}
}
return false;
}
template <class T>
bool Graph<T>::addEdge(const T &sourc, const T &dest, double distance, int line) {
typename vector<Vertex<T>*>::iterator it= vertexSet.begin();
typename vector<Vertex<T>*>::iterator ite= vertexSet.end();
int found=0;
Vertex<T> *vS, *vD;
while (found!=2 && it!=ite ) {
if ( (*it)->info == sourc )
{ vS=*it; found++;}
if ( (*it)->info == dest )
{ vD=*it; found++;}
it ++;
}
if (found!=2) return false;
vD->indegree++;
vS->addEdge(vD,distance,line);
return true;
}
template <class T>
bool Graph<T>::removeEdge(const T &sourc, const T &dest) {
typename vector<Vertex<T>*>::iterator it= vertexSet.begin();
typename vector<Vertex<T>*>::iterator ite= vertexSet.end();
int found=0;
Vertex<T> *vS, *vD;
while (found!=2 && it!=ite ) {
if ( (*it)->info == sourc )
{ vS=*it; found++;}
if ( (*it)->info == dest )
{ vD=*it; found++;}
it ++;
}
if (found!=2)
return false;
vD->indegree--;
return vS->removeEdgeTo(vD);
}
template <class T>
vector<T> Graph<T>::dfs() const {
typename vector<Vertex<T>*>::const_iterator it= vertexSet.begin();
typename vector<Vertex<T>*>::const_iterator ite= vertexSet.end();
for (; it !=ite; it++)
(*it)->visited=false;
vector<T> res;
it=vertexSet.begin();
for (; it !=ite; it++)
if ( (*it)->visited==false )
dfs(*it,res);
return res;
}
template <class T>
void Graph<T>::dfs(Vertex<T> *v,vector<T> &res) const {
v->visited = true;
res.push_back(v->info);
typename vector<Edge<T> >::iterator it= (v->adj).begin();
typename vector<Edge<T> >::iterator ite= (v->adj).end();
for (; it !=ite; it++)
if ( it->dest->visited == false ){
dfs(it->dest, res);
}
}
template <class T>
vector<T> Graph<T>::bfs(Vertex<T> *v) const {
vector<T> res;
queue<Vertex<T> *> q;
q.push(v);
v->visited = true;
while (!q.empty()) {
Vertex<T> *v1 = q.front();
q.pop();
res.push_back(v1->info);
typename vector<Edge<T> >::iterator it=v1->adj.begin();
typename vector<Edge<T> >::iterator ite=v1->adj.end();
for (; it!=ite; it++) {
Vertex<T> *d = it->dest;
if (d->visited==false) {
d->visited=true;
q.push(d);
}
}
}
return res;
}
template <class T>
int Graph<T>::maxNewChildren(Vertex<T> *v, T &inf) const {
vector<T> res;
queue<Vertex<T> *> q;
queue<int> level;
int maxChildren=0;
inf =v->info;
q.push(v);
level.push(0);
v->visited = true;
while (!q.empty()) {
Vertex<T> *v1 = q.front();
q.pop();
res.push_back(v1->info);
int l=level.front();
level.pop(); l++;
int nChildren=0;
typename vector<Edge<T> >::iterator it=v1->adj.begin();
typename vector<Edge<T> >::iterator ite=v1->adj.end();
for (; it!=ite; it++) {
Vertex<T> *d = it->dest;
if (d->visited==false) {
d->visited=true;
q.push(d);
level.push(l);
nChildren++;
}
}
if (nChildren>maxChildren) {
maxChildren=nChildren;
inf = v1->info;
}
}
return maxChildren;
}
template <class T>
Vertex<T>* Graph<T>::getVertex(const T &v) const {
for(unsigned int i = 0; i < vertexSet.size(); i++)
if (vertexSet[i]->info == v) return vertexSet[i];
return NULL;
}
template<class T>
void Graph<T>::resetIndegrees() {
//colocar todos os indegree em 0;
for(unsigned int i = 0; i < vertexSet.size(); i++) vertexSet[i]->indegree = 0;
//actualizar os indegree
for(unsigned int i = 0; i < vertexSet.size(); i++) {
//percorrer o vector de Edges, e actualizar indegree
for(unsigned int j = 0; j < vertexSet[i]->adj.size(); j++) {
vertexSet[i]->adj[j].dest->indegree++;
}
}
}
template<class T>
vector<Vertex<T>*> Graph<T>::getSources() const {
vector< Vertex<T>* > buffer;
for(unsigned int i = 0; i < vertexSet.size(); i++) {
if( vertexSet[i]->indegree == 0 ) buffer.push_back( vertexSet[i] );
}
return buffer;
}
template <class T>
void Graph<T>::dfsVisit() {
typename vector<Vertex<T>*>::const_iterator it= vertexSet.begin();
typename vector<Vertex<T>*>::const_iterator ite= vertexSet.end();
for (; it !=ite; it++)
(*it)->visited=false;
it=vertexSet.begin();
for (; it !=ite; it++)
if ( (*it)->visited==false )
dfsVisit(*it);
}
template <class T>
void Graph<T>::dfsVisit(Vertex<T> *v) {
v->processing = true;
v->visited = true;
typename vector<Edge<T> >::iterator it= (v->adj).begin();
typename vector<Edge<T> >::iterator ite= (v->adj).end();
for (; it !=ite; it++) {
if ( it->dest->processing == true) numCycles++;
if ( it->dest->visited == false ){
dfsVisit(it->dest);
}
}
v->processing = false;
}
template<class T>
vector<T> Graph<T>::topologicalOrder() {
//vector com o resultado da ordenacao
vector<T> res;
//verificar se é um DAG
if( getNumCycles() > 0 ) {
cout << "Ordenacao Impossivel!" << endl;
return res;
}
//garantir que os "indegree" estao inicializados corretamente
this->resetIndegrees();
queue<Vertex<T>*> q;
vector<Vertex<T>*> sources = getSources();
while( !sources.empty() ) {
q.push( sources.back() );
sources.pop_back();
}
//processar fontes
while( !q.empty() ) {
Vertex<T>* v = q.front();
q.pop();
res.push_back(v->info);
for(unsigned int i = 0; i < v->adj.size(); i++) {
v->adj[i].dest->indegree--;
if( v->adj[i].dest->indegree == 0) q.push( v->adj[i].dest );
}
}
//testar se o procedimento foi bem sucedido
if ( res.size() != vertexSet.size() ) {
while( !res.empty() ) res.pop_back();
}
//garantir que os "indegree" ficam atualizados ao final
this->resetIndegrees();
return res;
}
template<class T>
vector<T> Graph<T>::getPath(const T &origin, const T &dest){
list<T> buffer;
Vertex<T>* v = getVertex(dest);
//cout << v->info << " ";
buffer.push_front(v->info);
while ( v->path != NULL && v->path->info != origin) {
v = v->path;
buffer.push_front(v->info);
}
if( v->path != NULL )
buffer.push_front(v->path->info);
vector<T> res;
while( !buffer.empty() ) {
res.push_back( buffer.front() );
buffer.pop_front();
}
return res;
}
template<class T>
void Graph<T>::unweightedShortestPath(const T &s) {
for(unsigned int i = 0; i < vertexSet.size(); i++) {
vertexSet[i]->path = NULL;
vertexSet[i]->dist = INT_INFINITY;
}
Vertex<T>* v = getVertex(s);
v->dist = 0;
queue< Vertex<T>* > q;
q.push(v);
while( !q.empty() ) {
v = q.front(); q.pop();
for(unsigned int i = 0; i < v->adj.size(); i++) {
Vertex<T>* w = v->adj[i].dest;
if( w->dist == INT_INFINITY ) {
w->dist = v->dist + 1;
w->path = v;
q.push(w);
}
}
}
}
template<class T>
vector <Vertex<T>*> Graph<T>::bestPathFrom(const T &s) {
vector<Vertex<T>*> returnVector;
return returnVector;
}
template<class T>
T Graph<T>::getVertexbyId(int id){
for(int i = 0; i < vertexSet.size();i++){
if(vertexSet[i]->getInfo().getId() == id){
return vertexSet[i]->getInfo();
}
}
return vertexSet[0]->getInfo();
}
template<class T>
T*Graph<T>::getVertexbyIdPointer(int id){
for(int i = 0; i < vertexSet.size();i++){
if(vertexSet[i]->getInfo().getId() == id){
return vertexSet[i]->getInfoPointer();
}
}
return vertexSet[0]->getInfoPointer();
}
template<class T>
void Graph<T>::dijkstraShortestPath(const T &s) {
for(unsigned int i = 0; i < vertexSet.size(); i++) {
vertexSet[i]->path = NULL;
vertexSet[i]->dist = INT_INFINITY;
vertexSet[i]->processing = false;
}
Vertex<T>* v = getVertex(s);
v->dist = 0;
vector< Vertex<T>* > pq;
pq.push_back(v);
make_heap(pq.begin(), pq.end());
while( !pq.empty() ) {
v = pq.front();
pop_heap(pq.begin(), pq.end());
pq.pop_back();
for(unsigned int i = 0; i < v->adj.size(); i++) {
Vertex<T>* w = v->adj[i].dest;
int aValue = v->dist + v->adj[i].distance;
int bValue = w->dist;
bool condition = aValue < bValue;
if(condition) {
w->dist = v->dist + v->adj[i].distance;
w->path = v;
//se já estiver na lista, apenas a actualiza
if(!w->processing)
{
w->processing = true;
pq.push_back(w);
}
make_heap (pq.begin(),pq.end(),vertex_greater_than<T>());
}
}
}
vector<T> returnVector;
for(int i = 0; i < pq.size(); i++){
returnVector.push_back(pq[i]->getInfo());
}
}
#endif /* GRAPH_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment