#include <iostream>
#include <climits>
using namespace std;
template <typename t>
class minPriorityQueue {
int size, currentPosition;
int *position;
t *data;
bool (*compare)(t data1, t data2);
public:
minPriorityQueue(int size, bool (*func1)(t data1, t data2), int *position) {
this->size = size;
currentPosition = 1;
data = new t[size];
compare = func1;
this->position = position;
}
void swapPositionValue(int parent, int temp) {
if (position != NULL) {
int tempPosition = position[data[parent]];
position[data[parent]] = position[data[temp]];
position[data[temp]] = tempPosition;
}
}
void insert(t data) {
(this->data)[currentPosition] = data;
if(position != NULL) {
t temp = data[currentPosition];
position[temp] = currentPosition;
}
heapifyUp();
currentPosition++;
}
t & operator [](int k) {
return data[k];
}
t minElement() {
t ans = data[1];
data[1] = data[--currentPosition];
position[(data[currentPosition])] = 1;
this->heapifyDown();
return ans;
}
void heapifyDown() {
int current = 1;
int leftChild = 2*current, rightChild = leftChild + 1;
while(leftChild < currentPosition) {
if(rightChild < currentPosition) {
if(compare(data[leftChild], data[current]) && compare(data[rightChild], data[current])) {
return;
} else if(!compare(data[leftChild], data[rightChild])) {
t tempNode = data[leftChild];
data[leftChild] = data[current];
data[current] = tempNode;
current = leftChild;
swapPositionValue(current, leftChild);
} else {
t tempNode = data[rightChild];
data[rightChild] = data[current];
data[current] = tempNode;
current = rightChild;
swapPositionValue(current, rightChild);
}
} else {
if(compare(data[leftChild], data[current])) {
return;
} else {
t tempNode = data[leftChild];
data[leftChild] = data[current];
data[current] = tempNode;
current = leftChild;
swapPositionValue(current, leftChild);
}
}
leftChild = 2*current;
rightChild = leftChild + 1;
}
}
void heapifyUp() {
int temp = currentPosition;
int parent = temp / 2;
while(parent != 0) {
if(compare(data[parent], data[temp])) {
t tempNode = data[parent];
data[parent] = data[temp];
data[temp] = tempNode;
swapPositionValue(parent, temp);
} else {
break;
}
temp = parent;
parent = parent / 2;
}
}
void heapifyUp(int k) {
int temp = k;
int parent = temp / 2;
while(parent != 0) {
if(compare(data[parent], data[temp])) {
t tempNode = data[parent];
data[parent] = data[temp];
data[temp] = tempNode;
swapPositionValue(parent, temp);
} else {
break;
}
temp = parent;
parent = parent / 2;
}
}
bool isEmpty() {
if(currentPosition == 1)
return true;
return false;
}
~minPriorityQueue() {
delete [] data;
}
};
class graph{
protected:
class Node {
public:
int data;
int weight;
Node() {}
Node(int data) {
this->data = data;
this->weight = INT_MAX;
}
friend ostream & operator << (ostream & yo, Node d) {
yo << d.data;
return yo;
}
friend int& operator [](int *a, Node i) {
return a[i.data];
}
};
private:
bool **a;
const int numberOfNodes;
static bool compareNode(Node node1, Node node2) {
if(node1.weight > node2.weight)
return true;
return false;
}
public:
graph(int numberOfNodes) : numberOfNodes(numberOfNodes){
a = new bool *[numberOfNodes];
for(int i = 0; i < numberOfNodes; i++) {
a[i] = new bool[numberOfNodes]();
}
this->createGraph();
}
void singleSourceShortestPath(int source) {
int *parent = new int[numberOfNodes]();
int *position = new int[numberOfNodes]();
minPriorityQueue<Node> q(100, &compareNode, position);
Node newNode(source);
newNode.weight = 0;
parent[source] = source;
q.insert(newNode);
for(int i = 0; i < numberOfNodes; i++) {
if (i != source) {
Node newNode(i);
parent[i] = -1;
q.insert(newNode);
}
}
while(!q.isEmpty()) {
Node temp = q.minElement();
position[temp.data] = -1;
for(int i = 0; i < numberOfNodes; i++) {
if(a[temp.data][i] && position[i] != -1) {
Node changeNode = q[position[i]];
if((temp.weight + a[temp.data][i]) < changeNode.weight) {
changeNode.weight = temp.weight + a[temp.data][i];
q.heapifyUp(position[i]);
parent[i] = temp.data;
}
}
}
}
delete [] parent;
delete [] position;
}
void createGraph() {
addEdge(0,2);
addEdge(1,0);
addEdge(5,0);
addEdge(1,5);
addEdge(3,1);
addEdge(3,2);
addEdge(5,4);
addEdge(4,2);
}
void addEdge(int start, int end) {
if(start >= numberOfNodes || start < 0 || end >= numberOfNodes || end < 0)
return;
a[start][end] = true;
}
~graph() {
for(int i = 0; i < this->numberOfNodes; i++) {
delete [] a[i];
}
delete [] a;
}
};
int main(int argc, char** argv) {
graph g1(6);
g1.singleSourceShortestPath(3);
return 0;
}