Øvelse: Implementér Dijkstra's Algoritme
Øvelsesbeskrivelse
I denne øvelse skal I implementere Dijkstra's algoritme i Processing til at finde korteste afstande i en graf, som er repræsenteret med en adjacency matrix. (nabo matrice)
Opgaver:
Tegn først grafen på papir ud fra en adjacency matrix, som I selv skal definere i koden.
I skal opdele programmet i funktioner, der hver især har et klart ansvar:
Initialisering af søgealgoritmens arrays (afstande og besøgte noder)
Selve Dijkstra-algoritmen
Funktion til at finde den næste node med kortest kendt afstand
Udskrivning af resultaterne i et overskueligt format
Hjælpefunktion til at konvertere nodeindeks til navne (fx 0 → 'A') (optionel men rar at have:-))
Jeg har lavet en skabelon, hvor funktionerne er tomme. Jeres opgave er at implementere funktionerne.
Test jeres løsning med forskellige grafer og startnoder.
Hvad er en adjacency matrix?
En adjacency matrix er en måde at repræsentere en graf (netværk af noder og kanter) på ved hjælp af et to-dimensionel array (et gitter af tal).
Hver række og kolonne svarer til en node i grafen.
Værdien i matrix[c][r] viser vægten (afstand, pris eller omkostning) af kanten mellem node c og node r.
Hvis der ikke er registreret nogen forbindelse mellem to noder angives dette typisk med et stort tal (fx „∞“ eller Integer.MAX_VALUE).
Diagonal-elementerne (sammen med sig selv) er normalt 0, fordi afstanden fra en node til sig selv er nul.
Eksempel på adjacency matrix for 5 noder (A til E)
A B C D E
A [0, 4, ∞, 2, ∞]
B [4, 0, 3, ∞, ∞]
C [∞, 3, 0, 1, 6]
D [2, ∞, 1, 0, 3]
E [∞, ∞, 6, 3, 0]
I matrix’en ovenfor betyder fx tallet 4 i position (A,B), at kanten fra node A til node B har vægten 4, mens „∞“ betyder, at forbindelsen ikke er registreret endnu eller ukendt.
Skabelon med funktioner
final int INF = Integer.MAX_VALUE;
int[][] matrix; // Nabo matrice
int nodeCount; // antallet af nodes
int[] distances; // afstande fra startNode.
boolean[] visited; // liste over besøgte nodes. (true, hvis besøgt)
int[] parent; // liste
int startNode;
void setup() {
// Initialiser variabler her, fx matrix, nodeCount og startNode
initSearch();
runDijkstra(startNode);
printResults();
}
// Initialiserer distances- og besøgte nodes
void initSearch() {
// - Sæt startnode afstand til 0, og alle andre afstande til ∞.
// - Marker alle nodes som __ikke besøgte__.
}
// Kører Dijkstra's algoritme
void runDijkstra(int startNode) {
// TODO: Implementér algoritmen
}
// Finder næste node med kortest kendt afstand som _ikke_ er besøgt
int minDistanceNode() {
// returneres der -1, betyder det, at enten er alle noder besøgt, eller at de resterende noder ikke er forbundne med startnoden
return -1; // Midlertidig return
}
// Printer resultatet med afstande fra startnode
void printResults() {
// TODO: Implementér udskrivning.
// Udskrivning af korteste vej.
}
// Hjælpefunktion der giver et bogstavnavn til node ud fra index (fx 0 -> A)
String nodeName(int index) {
// TODO: Implementér konvertering fra index til navn
return "";
}
Hints og eksempler på implementering
InitSearch
Initialiser distances til INF for alle noder
Sæt distances[start] til 0
Initialiser visited til false for alle noder
Initialiser parent til -1 for alle noder (ingen parent endnu)
FindMinDistance
Sæt min til INF
Sæt minIndex til -1
For hver node v:
Hvis visited[v] == false og distances[v] <= min:
min = distances[v]
minIndex = v
Returner minIndex
RunDijkstra
Kald InitSearch(start)
Gentag for nodeCount gange:
u = FindMinDistance()
Hvis u == -1:
Stop løkken
visited[u] = true
For hver node v:
Hvis visited[v] == false og der findes kant mellem u og v:
Hvis distances[u] + graph[u,v] < distances[v]:
distances[v] = distances[u] + graph[u,v]
parent[v] = u // Opdater parent for v
PrintResults
Skriv "Korteste afstande fra node " + NodeName(start) + ":"
For hver node v:
Hvis distances[v] == INF:
distStr = "∞"
Ellers:
distStr = distances[v].ToString()
Skriv NodeName(start) + " → " + NodeName(v) + ": " + distStr
PrintPath
Funktion PrintPath(parent, start, end):
Hvis end == start:
Udskriv NodeName(start)
Stop
Hvis parent[end] == -1:
Udskriv "Ingen sti fra " + NodeName(start) + " til " + NodeName(end)
Stop
PrintPath(parent, start, parent[end])
Udskriv " → " + NodeName(end)
Test af Algoritme
Når du er færdig, kan du teste koden ved at initialisere din matrix, nodeCount og startNode i setup(), og køre programmet. (test din algoritme på nedestående matrice)
matrix = new int[][] {
// A B C D E
{ 0, 6, INF, 1, INF}, // A
{ 6, 0, 5, 2, 2 }, // B
{INF, 5, 0, INF, 5 }, // C
{ 1, 2, INF, 0, 1 }, // D
{INF, 2, 5, 1, 0 } // E
};
Korteste sti fra A til C er:
A -> D -> E -> C
Afstand: 7