Files
2026-03-05 13:39:39 +01:00

286 lines
7.6 KiB
C++

/************************************************
* Laboration 4 i
* Datastrukturer och Algoritmer
* Dijkstras Shortest Path
*************************************************
* Christian Ohlsson
* Karlstads universitet, 1999
*
* graf.cpp
* Innehåller de funktioner programmet
* använder sig av för att beräkna
* den kortaste vägen
*************************************************/
#include "header.h"
/*===============================================
* graphNode
* Construktor.
* Skapar en graphNode
-------------------------------------------------*/
graphNode::graphNode() {
startCity = -1;
endCity = -1;
Start = 0;
End = 0;
}
/*===============================================
* Operator ==
* Operatoröverlagring
-------------------------------------------------*/
int graphNode::operator==(graphNode node) {
if(Start != node.Start || End != node.End ||
startCity != node.startCity || endCity != node.endCity)
return false;
return true;
}
/*===============================================
* Operator =
* Operatoröverlagring
-------------------------------------------------*/
void graphNode::operator=(graphNode node) {
startCity = node.startCity;
endCity = node.endCity;
Start = node.Start;
End = node.End;
}
/*===============================================
* Operator >
* Operatoröverlagring
-------------------------------------------------*/
int graphNode::operator>(graphNode node) {
if(Start <= node.Start)
return false;
return true;
}
/*===============================================
* dijkstraNode
* Construktor.
* Skapar en Dijkstra node
-------------------------------------------------*/
dijkstraNode::dijkstraNode() {
deleted = false;
lastCity = 0;
Totaltime = MAXINT; //Tiden sätts till max
}
/*===============================================
* ~dijkstraNode
* Destruktor.
* Tar bort en nod
-------------------------------------------------*/
dijkstraNode::~dijkstraNode() {}
/*===============================================
* graph
* Construktor
* Skapar en graph
-------------------------------------------------*/
graph::graph() {
visitedCities = 0;
table = NULL;
lastPath = NULL;
prevSize = 0;
lastTime = 0;
}
/*===============================================
* ~graph
* Destruktor
* Anropar deleteGraph
-------------------------------------------------*/
graph::~graph() { deleteGraph(); }
/*===============================================
* deleteGraph
* Tömmer grafen på info
-------------------------------------------------*/
void graph::deleteGraph() {
if(table != NULL)
delete[] table;
if(lastPath != NULL)
delete[] lastPath;
table = NULL;
lastPath = NULL;
visitedCities = 0;
prevSize = 0;
lastTime = 0;
}
/*===============================================
* makeGraph
* Skapar en graf med size stycken städer.
* Tar först bort eventuell gammal graf.
* Returnerar true om allt gick bra
-------------------------------------------------*/
int graph::makeGraph(int size) {
deleteGraph();
table = new list<graphNode>*[size];
if(table == NULL)
return false;
for(int index = 0; index < size; index++)
table[index] = new list<graphNode>[size];
if(table == NULL)
return false;
visitedCities = size;
return true;
}
/*===============================================
* connect
* Skapar förbindelse mellan noderna i grafen
-------------------------------------------------*/
void graph::connect(int startvertex, int endvertex, graphNode node) {
if(startvertex < 0 || startvertex > visitedCities-1 ||
endvertex < 0 || endvertex > visitedCities-1)
return;
node.startCity = startvertex;
node.endCity = endvertex;
table[startvertex][endvertex].insert(node);
}
/*===============================================
* shortestPath
* Letar reda på den kortaste
* vägen mellan två noder
-------------------------------------------------*/
graphNode graph::shortestPath(int startvertex, int endvertex, int time) {
int index, time1, time2;
graphNode node1, node2;
if(startvertex < 0 || startvertex > visitedCities-1 ||
endvertex < 0 || endvertex > visitedCities-1)
return node1;
int connections = table[startvertex][endvertex].listLength();
if(connections == 0) return node1;
node1 = table[startvertex][endvertex].printElement(1);
time1 = getTime(node1, time);
for(index = 2; index <= connections; index++) {
node2 = table[startvertex][endvertex].printElement(index);
time2 = getTime(node2, time);
if(time1 > time2) {
node1 = node2;
time1 = time2;
}
}
return node1;
}
/*===============================================
* getTime
* Returnerar antalet timmar mellan tiden
* time och tiden som finns i noden
-------------------------------------------------*/
int graph::getTime(graphNode node, int time) {
int total;
if(node.Start >= time && node.End > time && node.Start < node.End)
total = node.End - time;
else if(node.Start > node.End)
total = ( (24 - time + node.Start) + (24 - node.Start + node.End) );
else
total = (24 - time + node.End);
return total;
}
/*===============================================
* dijkstra
* Beräknar den kortaste sträckan dvs. tiden
* mellan två städer i NeverNeverLand
-------------------------------------------------*/
void graph::dijkstra(int startvertex, int endvertex, int time) {
delPath();
if(startvertex == endvertex || startvertex < 0 ||
startvertex > visitedCities-1 || endvertex < 0 ||
endvertex > visitedCities-1)
return;
dijkstraNode *temparray = new dijkstraNode[visitedCities];
if(temparray == NULL) return;
int min, index, parent = 0, temptime;
graphNode tempnode;
temparray[startvertex].Totaltime = 0;
temparray[startvertex].deleted = true;
min = startvertex;
while(min != endvertex) {
for(index = 0; index < visitedCities; index++) {
if(!temparray[index].deleted) {
tempnode = shortestPath(min, index, time);
if(tempnode.startCity != -1) {
temptime = getTime(tempnode, time);
if((temptime + temparray[min].Totaltime)
< temparray[index].Totaltime) {
temparray[index].Totaltime =
temptime + temparray[min].Totaltime;
if(parent == 0)
temparray[index].lastCity = 0;
else
temparray[index].lastCity = min;
temparray[index].Node = tempnode;
}
}
}
}
min = getMinTime(temparray);
temparray[min].deleted = true;
time = temparray[min].Node.End;
parent++;
}
calcPath(temparray, min);
}
/*===============================================
* calcPath
* Skapar en array med information
* om den kortaste vägen.
-------------------------------------------------*/
void graph::calcPath(dijkstraNode *array, int start) {
graphNode *path = new graphNode[visitedCities];
if(path == NULL)
return;
int temp = 1, index = start;
while(array[index].lastCity > 0) {
temp++;
index = array[index].lastCity;
}
prevSize = temp;
lastTime = array[start].Totaltime;
for(index = temp-1; index >= 0; index--) {
path[index] = array[start].Node;
start = array[start].lastCity;
}
lastPath = path;
}
/*===============================================
* getMinIndex
* Hittar den minsta noden i en array och
* returnerar dess index i arrayen
-------------------------------------------------*/
int graph::getMinTime(dijkstraNode *temptable) {
int temp = 0, index;
while(temptable[temp].deleted)
temp++;
for(index = temp+1; index < visitedCities; index++) {
if(!temptable[index].deleted) {
if(temptable[temp].Totaltime > temptable[index].Totaltime)
temp = index;
}
}
return temp;
}
/*===============================================
* delPath
* Tar bort det som lastpath pekar på
-------------------------------------------------*/
void graph::delPath() {
if(lastPath != NULL)
delete[] lastPath;
lastPath = NULL;
prevSize = 0;
}