Skip to content

Commit 6af84eb

Browse files
Dijkstra algorithm
1 parent f1d3085 commit 6af84eb

File tree

6 files changed

+204
-2
lines changed

6 files changed

+204
-2
lines changed

src/main/kotlin/pl/dmichalski/algorithms/data_structures/_11_graph_traversal/Runner.kt

-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ object Runner {
3232
val breadthFirstSearch = undirectedGraph.breadthFirstSearch(VERTEX_A)
3333
println("Graph elements: $breadthFirstSearch")
3434
printUndirectedGraph(undirectedGraph)
35-
36-
3735
}
3836

3937
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package pl.dmichalski.algorithms.data_structures._12_dijkstra_algorithm
2+
3+
class Connection(private val vertex: String, private val weight: Int) {
4+
5+
fun getVertex(): String {
6+
return vertex
7+
}
8+
9+
fun getWeight(): Int {
10+
return weight
11+
}
12+
13+
override fun toString(): String {
14+
return "Connection(vertex='$vertex', weight=$weight)"
15+
}
16+
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package pl.dmichalski.algorithms.data_structures._12_dijkstra_algorithm
2+
3+
data class Node(private val vertex: String, private val connections: MutableList<Connection>) {
4+
5+
fun getVertex(): String {
6+
return vertex
7+
}
8+
9+
fun getConnections(): MutableList<Connection> {
10+
return connections
11+
}
12+
13+
override fun toString(): String {
14+
return "Node(vertex='$vertex', connections=$connections)"
15+
}
16+
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package pl.dmichalski.algorithms.data_structures._12_dijkstra_algorithm
2+
3+
class QueueNode(private val value: String, private val priority: Int) {
4+
5+
fun getValue(): String {
6+
return value
7+
}
8+
9+
fun getPriority(): Int {
10+
return priority
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package pl.dmichalski.algorithms.data_structures._12_dijkstra_algorithm
2+
3+
object Runner {
4+
5+
private const val VERTEX_A = "A"
6+
private const val VERTEX_B = "B"
7+
private const val VERTEX_C = "C"
8+
private const val VERTEX_D = "D"
9+
private const val VERTEX_E = "E"
10+
private const val VERTEX_F = "F"
11+
12+
@JvmStatic
13+
fun main(args: Array<String>) {
14+
println("------------------ Initial weighted graph ------------------ ")
15+
var weightedGraph = getWeightedGraph()
16+
printWeightedGraph(weightedGraph)
17+
18+
println("------------------ Finding the shortest path using Dijkstra algorithm ------------------ ")
19+
weightedGraph = getWeightedGraph()
20+
val shortestPath = weightedGraph.dijkstra(VERTEX_A, VERTEX_E)
21+
println("Shortest path between $VERTEX_A and $VERTEX_E: $shortestPath")
22+
}
23+
24+
/**
25+
* It returns weighted graph like this:
26+
* <pre>
27+
* 4
28+
* A --------- B
29+
* 2 / |
30+
* / 2 |
31+
* C ------- D | 3
32+
* \ / \ |
33+
* 4 \ 1 / \ 3 |
34+
* \ / \ |
35+
* F --------- E
36+
* 1
37+
*
38+
* </pre>
39+
*/
40+
private fun getWeightedGraph(): WeightedGraph {
41+
val weightedGraph = WeightedGraph()
42+
43+
weightedGraph.addVertex(VERTEX_A)
44+
weightedGraph.addVertex(VERTEX_B)
45+
weightedGraph.addVertex(VERTEX_C)
46+
weightedGraph.addVertex(VERTEX_D)
47+
weightedGraph.addVertex(VERTEX_E)
48+
weightedGraph.addVertex(VERTEX_F)
49+
50+
weightedGraph.addEdge(VERTEX_A, VERTEX_B, 4)
51+
weightedGraph.addEdge(VERTEX_A, VERTEX_C, 2)
52+
weightedGraph.addEdge(VERTEX_B, VERTEX_E, 3)
53+
weightedGraph.addEdge(VERTEX_C, VERTEX_D, 2)
54+
weightedGraph.addEdge(VERTEX_C, VERTEX_F, 4)
55+
weightedGraph.addEdge(VERTEX_D, VERTEX_E, 3)
56+
weightedGraph.addEdge(VERTEX_D, VERTEX_F, 1)
57+
weightedGraph.addEdge(VERTEX_E, VERTEX_F, 1)
58+
59+
return weightedGraph
60+
}
61+
62+
private fun printWeightedGraph(weightedGraph: WeightedGraph) {
63+
println(weightedGraph)
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package pl.dmichalski.algorithms.data_structures._12_dijkstra_algorithm
2+
3+
import java.util.*
4+
import kotlin.collections.ArrayList
5+
import kotlin.collections.HashMap
6+
7+
class WeightedGraph {
8+
9+
private val adjacencyList: MutableList<Node> = ArrayList()
10+
11+
fun addVertex(vertex: String) {
12+
val node = findNode(vertex)
13+
14+
if (node == null) {
15+
val newNode = Node(vertex, mutableListOf())
16+
this.adjacencyList.add(newNode)
17+
}
18+
}
19+
20+
fun addEdge(vertex1: String, vertex2: String, weight: Int) {
21+
val node1 = findNode(vertex1)
22+
val node2 = findNode(vertex2)
23+
24+
val connection1 = Connection(vertex1, weight)
25+
val connection2 = Connection(vertex2, weight)
26+
27+
node1!!.getConnections().add(connection2)
28+
node2!!.getConnections().add(connection1)
29+
}
30+
31+
fun dijkstra(start: String, finish: String): List<String> {
32+
val compareByWeight: Comparator<QueueNode> = compareBy { it.getPriority() }
33+
val nodesQueue = PriorityQueue(compareByWeight)
34+
val path: MutableList<String> = ArrayList()
35+
36+
val distances = HashMap<String, Int>(adjacencyList.size)
37+
val previous = HashMap<String, String?>(adjacencyList.size)
38+
var smallest: String
39+
40+
for (vertexNode in adjacencyList) {
41+
val vertex = vertexNode.getVertex()
42+
if (vertex == start) {
43+
distances[vertex] = 0
44+
val queueNode = QueueNode(vertex, 0)
45+
nodesQueue.add(queueNode)
46+
} else {
47+
distances[vertex] = Int.MAX_VALUE
48+
val queueNode = QueueNode(vertex, Int.MAX_VALUE)
49+
nodesQueue.add(queueNode)
50+
}
51+
previous[vertex] = null
52+
}
53+
54+
while (nodesQueue.size > 0) {
55+
smallest = nodesQueue.poll().getValue()
56+
if (smallest === finish) {
57+
while (previous[smallest] != null) {
58+
path.add(smallest)
59+
smallest = previous[smallest]!!
60+
}
61+
break
62+
}
63+
if (distances[smallest] != Int.MAX_VALUE) {
64+
val node = adjacencyList.first { vertexNode -> vertexNode.getVertex() === smallest }
65+
for (neighbor in node.getConnections()) {
66+
val candidate = distances[smallest]?.plus(neighbor.getWeight())
67+
val nextNeighbor = neighbor.getVertex()
68+
if (candidate!! < distances[nextNeighbor]!!) {
69+
distances[nextNeighbor] = candidate
70+
previous[nextNeighbor] = smallest
71+
val queueNode = QueueNode(nextNeighbor, candidate)
72+
nodesQueue.add(queueNode)
73+
}
74+
}
75+
}
76+
}
77+
78+
return path
79+
}
80+
81+
override fun toString(): String {
82+
return "UndirectedGraph(adjacencyList='$adjacencyList')\n"
83+
}
84+
85+
private fun findNode(vertex: String): Node? {
86+
return adjacencyList.stream()
87+
.filter { node -> node.getVertex() == vertex }
88+
.findFirst()
89+
.orElse(null)
90+
}
91+
92+
}

0 commit comments

Comments
 (0)