




#ifndef INC_03_IMPLEMENTATION_OF_DIJKSTRA_SPARSEGRAPH_H
#define INC_03_IMPLEMENTATION_OF_DIJKSTRA_SPARSEGRAPH_H
#include <iostream>
#include <vector>
#include <cassert>
#include "Edge.h"
using namespace std;
template<typename Weight>
class SparseGraph{
private:
int n, m;
bool directed;
vector<vector<Edge<Weight> *> > g;
public:
SparseGraph( int n , bool directed){
assert(n >= 0);
this->n = n;
this->m = 0;
this->directed = directed;
g = vector<vector<Edge<Weight> *> >(n, vector<Edge<Weight> *>());
}
~SparseGraph(){
for( int i = 0 ; i < n ; i ++ )
for( int j = 0 ; j < g[i].size() ; j ++ )
delete g[i][j];
}
int V(){ return n;}
int E(){ return m;}
void addEdge( int v, int w , Weight weight){
assert( v >= 0 && v < n );
assert( w >= 0 && w < n );
g[v].push_back(new Edge<Weight>(v, w, weight));
if( v != w && !directed )
g[w].push_back(new Edge<Weight>(w, v, weight));
m ++;
}
bool hasEdge( int v , int w ){
assert( v >= 0 && v < n );
assert( w >= 0 && w < n );
for( int i = 0 ; i < g[v].size() ; i ++ )
if( g[v][i]->other(v) == w )
return true;
return false;
}
void show(){
for( int i = 0 ; i < n ; i ++ ){
cout<<"vertex "<<i<<":\t";
for( int j = 0 ; j < g[i].size() ; j ++ )
cout<<"( to:"<<g[i][j]->w()<<",wt:"<<g[i][j]->wt()<<")\t";
cout<<endl;
}
}
class adjIterator{
private:
SparseGraph &G;
int v;
int index;
public:
adjIterator(SparseGraph &graph, int v): G(graph){
this->v = v;
this->index = 0;
}
~adjIterator(){}
Edge<Weight>* begin(){
index = 0;
if( G.g[v].size() )
return G.g[v][index];
return NULL;
}
Edge<Weight>* next(){
index += 1;
if( index < G.g[v].size() )
return G.g[v][index];
return NULL;
}
bool end(){
return index >= G.g[v].size();
}
};
};
#endif
#ifndef INC_03_IMPLEMENTATION_OF_DIJKSTRA_EDGE_H
#define INC_03_IMPLEMENTATION_OF_DIJKSTRA_EDGE_H
#include <iostream>
#include <cassert>
using namespace std;
template<typename Weight>
class Edge{
private:
int a,b;
Weight weight;
public:
Edge(int a, int b, Weight weight){
this->a = a;
this->b = b;
this->weight = weight;
}
Edge(){}
~Edge(){}
int v(){ return a;}
int w(){ return b;}
Weight wt(){ return weight;}
int other(int x){
assert( x == a || x == b );
return x == a ? b : a;
}
friend ostream& operator<<(ostream &os, const Edge &e){
os<<e.a<<"-"<<e.b<<": "<<e.weight;
return os;
}
bool operator<(Edge<Weight>& e){
return weight < e.wt();
}
bool operator<=(Edge<Weight>& e){
return weight <= e.wt();
}
bool operator>(Edge<Weight>& e){
return weight > e.wt();
}
bool operator>=(Edge<Weight>& e){
return weight >= e.wt();
}
bool operator==(Edge<Weight>& e){
return weight == e.wt();
}
};
#endif
#ifndef INC_03_IMPLEMENTATION_OF_DIJKSTRA_READGRAPH_H
#define INC_03_IMPLEMENTATION_OF_DIJKSTRA_READGRAPH_H
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cassert>
using namespace std;
template <typename Graph, typename Weight>
class ReadGraph{
public:
ReadGraph(Graph &graph, const string &filename){
ifstream file(filename);
string line;
int V, E;
assert(file.is_open());
assert( getline(file,line));
stringstream ss(line);
ss >> V >> E;
assert( graph.V() == V );
cout << V << " " << E << endl;
for( int i = 0 ; i < E ; i ++ ){
assert( getline(file,line));
stringstream ss(line);
int a, b;
Weight w;
ss>>a>>b>>w;
assert( a >= 0 && a < V );
assert( b >= 0 && b < V );
graph.addEdge(a, b, w);
}
}
};
#endif
#ifndef INC_03_IMPLEMENTATION_OF_DIJKSTRA_INDEXMINHEAP_H
#define INC_03_IMPLEMENTATION_OF_DIJKSTRA_INDEXMINHEAP_H
#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;
template<typename Item>
class IndexMinHeap{
private:
Item *data;
int *indexes;
int *reverse;
int count;
int capacity;
void shiftUp( int k ){
while( k > 1 && data[indexes[k/2]] > data[indexes[k]] ){
swap( indexes[k/2] , indexes[k] );
reverse[indexes[k/2]] = k/2;
reverse[indexes[k]] = k;
k /= 2;
}
}
void shiftDown( int k ){
while( 2*k <= count ){
int j = 2*k;
if( j + 1 <= count && data[indexes[j]] > data[indexes[j+1]] )
j += 1;
if( data[indexes[k]] <= data[indexes[j]] )
break;
swap( indexes[k] , indexes[j] );
reverse[indexes[k]] = k;
reverse[indexes[j]] = j;
k = j;
}
}
public:
IndexMinHeap(int capacity){
data = new Item[capacity+1];
indexes = new int[capacity+1];
reverse = new int[capacity+1];
for( int i = 0 ; i <= capacity ; i ++ )
reverse[i] = 0;
count = 0;
this->capacity = capacity;
}
~IndexMinHeap(){
delete[] data;
delete[] indexes;
delete[] reverse;
}
int size(){
return count;
}
bool isEmpty(){
return count == 0;
}
void insert(int index, Item item){
assert( count + 1 <= capacity );
assert( index + 1 >= 1 && index + 1 <= capacity );
index += 1;
data[index] = item;
indexes[count+1] = index;
reverse[index] = count+1;
count++;
shiftUp(count);
}
Item extractMin(){
assert( count > 0 );
Item ret = data[indexes[1]];
swap( indexes[1] , indexes[count] );
reverse[indexes[count]] = 0;
reverse[indexes[1]] = 1;
count--;
shiftDown(1);
return ret;
}
int extractMinIndex(){
assert( count > 0 );
int ret = indexes[1] - 1;
swap( indexes[1] , indexes[count] );
reverse[indexes[count]] = 0;
reverse[indexes[1]] = 1;
count--;
shiftDown(1);
return ret;
}
Item getMin(){
assert( count > 0 );
return data[indexes[1]];
}
int getMinIndex(){
assert( count > 0 );
return indexes[1]-1;
}
bool contain( int index ){
return reverse[index+1] != 0;
}
Item getItem( int index ){
assert( contain(index) );
return data[index+1];
}
void change( int index , Item newItem ){
assert( contain(index) );
index += 1;
data[index] = newItem;
shiftUp( reverse[index] );
shiftDown( reverse[index] );
}
};
#endif
#include <iostream>
#include <vector>
#include <cassert>
#include <stack>
#include "Edge.h"
#include "IndexMinHeap.h"
#include "SparseGraph.h"
#include "ReadGraph.h"
using namespace std;
template<typename Graph, typename Weight>
class Dijkstra{
private:
Graph &G;
int s;
Weight *distTo;
bool *marked;
vector<Edge<Weight>*> from;
public :
Dijkstra(Graph &graph, int s):G(graph){
assert(s >=0 && s < G.V());
this->s = s;
distTo = new Weight[G.V()];
marked = new bool[G.V()];
for(int i= 0; i < G.V(); i++){
distTo[i] = Weight();
marked[i] = false;
from.push_back(NULL);
}
IndexMinHeap<Weight> ipq(G.V());
distTo[s] = Weight();
from[s] = new Edge<Weight>(s, s, Weight());
ipq.insert(s, distTo[s]);
marked[s] = true;
while (!ipq.isEmpty()){
int v = ipq.extractMinIndex();
marked[v] = true;
typename Graph::adjIterator adj(G, v);
for (Edge<Weight>* e = adj.begin(); !adj.end(); e = adj.next()) {
int w = e->other(v);
if(!marked[w]){
if (from[w] == NULL || distTo[v]+e->wt() < distTo[w]){
distTo[w] = distTo[v]+e->wt();
from[w] = e;
if (ipq.contain(w))
ipq.change(w, distTo[w]);
else
ipq.insert(w, distTo[w]);
}
}
}
}
for (int i = 0; i < G.V(); i++) {
cout<< marked[i] <<endl;
}
}
~Dijkstra(){
delete[] distTo;
delete[] marked;
delete from[0];
};
bool hasEdgTo(int w){
assert( w >= 0 && w < G.V());
return marked[w];
}
Weight shortestPathTo(int w){
assert( w >= 0 && w < G.V());
assert(hasEdgTo(w));
return distTo[w];
}
void shortestPath(int w, vector<Edge<Weight>> &vec){
assert( w >= 0 && w < G.V());
assert(hasEdgTo(w));
stack<Edge<Weight>*> s;
Edge<Weight> *e = from[w];
while (e->v() != this->s){
s.push(e);
e = from[e->v()];
}
s.push(e);
while (!s.empty()){
e = s.top();
vec.push_back(*e);
s.pop();
}
}
void showPath(int w){
assert( w >= 0 && w < G.V());
assert(hasEdgTo(w));
vector<Edge<Weight>> vec;
shortestPath(w, vec);
for (int i = 0; i < vec.size(); i++) {
cout<< vec[i].v()<< " - >";
if (i==vec.size()-1)
cout<< vec[i].w()<< endl;
}
}
};
int main (){
string filename = "/Users/ericli/CLionProjects/lijunshi/day16/testG1.txt";
int V = 5;
SparseGraph<int> g = SparseGraph<int>(V, true);
ReadGraph<SparseGraph<int>, int> readGraph(g, filename);
Dijkstra<SparseGraph<int>, int> dij(g, 0);
dij.showPath(4);
return 0;
}
5 8
0 1 5
0 2 2
0 3 6
1 4 1
2 1 1
2 4 5
2 3 3
3 4 2
