|
| 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