fun main() {
var mapGraph = MapGraph(6)
mapGraph.addEdge(0, 1, 5)
mapGraph.addEdge(0, 5, 8)
mapGraph.addEdge(1, 4, 2)
mapGraph.addEdge(1, 2, 8)
mapGraph.addEdge(2, 3, 2)
mapGraph.addEdge(3, 5, 1)
mapGraph.addEdge(4, 3, 3)
mapGraph.dijkstra(0, 5)
}
/**
* @param sid 起始顶点
* @param tid 终止顶点
* @param weight 权重
*/
class Edge(var sid: Int, var tid: Int, var weight: Int)
/**
* @param sid 顶点编号
* @param dist 从起始顶点到该顶点的距离
*/
class Vertex(var sid: Int, var dist: Int)
class MapGraph(val size: Int) {
private var adj = Array(size) {
java.util.LinkedList()
}
fun addEdge(sid: Int, tid: Int, w: Int) {
var edge = Edge(sid, tid, w)
adj[sid].add(edge)
}
fun dijkstra(s: Int, t: Int) {
//用来还原最短路径
var predecessor = Array(size){ -1 }
var vertexes = Array(size) {
Vertex(it, Int.MAX_VALUE)
}
//小顶堆
var queue = PriorityQueue(size)
var inqueue = Array(size) { false }
vertexes[s].dist = 0
queue.add(vertexes[s])
inqueue[s] = true
while (!queue.isEmpty()) {
//取出堆顶
var minVertex: Vertex = queue.poll()!!
//最短路径产生
if (minVertex.sid == t) {
break
}
for (i in adj[minVertex.sid].indices) {
//取出一条 minVertex 相连的边
var edge = adj[minVertex.sid][i]
// minVertex -> nextVertex
var nextVertex = vertexes[edge.tid]
if (minVertex.dist + edge.weight < nextVertex.dist) {
nextVertex.dist = minVertex.dist + edge.weight
predecessor[nextVertex.sid] = minVertex.sid
if (inqueue[nextVertex.sid]) {
queue.update(nextVertex)
} else {
queue.add(nextVertex)
inqueue[nextVertex.sid] = true
}
}
}
}
printPath(s, t, predecessor)
}
private fun printPath(s: Int, t: Int, predecessor: Array) {
if (s == t) {
print("$s")
return
}
var pre = predecessor[t]
if (pre < 0) {
return
}
printPath(s, pre, predecessor)
print("->${t}")
}
}
class PriorityQueue(val size: Int) {
private val nodes: Array = Array(size) {
null
}
private var realCount = 0
fun poll(): Vertex? {
if (realCount == 0) {
return null
}
var item = nodes[0]
nodes[0] = nodes[realCount - 1]
nodes[realCount - 1] = null
realCount--
//自上而下进行堆化
heapifyUpToDown(0)
return item
}
fun add(vertex: Vertex): Boolean {
if (realCount == size) {
return false
}
nodes[realCount++] = vertex
//自下而上进行堆化
heapifyDownToUp(realCount - 1)
return true
}
fun update(vertex: Vertex): Boolean {
for (i in 0 until realCount) {
if (nodes[i]!!.sid == vertex.sid) {
nodes[i]!!.dist = vertex.dist
var p = i
while (p >= 0) {
var up = (p - 1) / 2
heapifyUpToDown(p)
if (up >= 0 && nodes[up]!!.dist <= nodes[p]!!.dist) {
break
}
p = up
}
return true
}
}
return false
}
fun isEmpty(): Boolean = realCount == 0
fun heapifyUpToDown(i: Int) {
var p = i
while (p < realCount) {
var minPos = p
var left = p * 2 + 1
var right = left + 1
if (left < realCount && nodes[left]!!.dist < nodes[minPos]!!.dist) {
minPos = left
}
if (right < realCount && nodes[right]!!.dist < nodes[minPos]!!.dist) {
minPos = right
}
if (p == minPos) {
break
}
swap(p, minPos)
p = minPos
}
}
fun heapifyDownToUp(i: Int) {
var p = i
while (p > 0) {
var up = (p - 1) / 2
if (nodes[p]!!.dist < nodes[up]!!.dist) {
swap(p, up)
p = up
} else {
break
}
}
}
fun swap(i: Int, j: Int) {
var tmp = nodes[i]
nodes[i] = nodes[j]
nodes[j] = tmp
}
}