Skip to content
← 返回算法列表
问题与数据结构

Dijkstra 最短路 ​

图

说明 ​

反复确定当前距离最小的顶点;只适用于非负边权。

分析 ​

dist 记录目前已知的最短距离,每轮固定尚未处理且距离最小的顶点,再尝试松弛其出边。非负权重保证固定后的距离不会再变小。

图解推演

正文先固定距离为 0 的顶点 0,松弛得到 dist[1]=2;再固定 1,得到 dist[2]=5。补充反例:若 0→A=2、0→B=5、B→A=−4,A 会被过早固定为 2,实际应为 1。非负边是正确性前提,不能只把负数也塞进同一实现。

查看图表代码

适用前提与边界 ​

示例使用简单的 O(V²+E) 扫描;大型稀疏图可用堆降低选点成本。

示例输入与调用 ​

go
fmt.Println(Dijkstra([][]Edge{{{To: 1, Weight: 2}}, {{To: 2, Weight: 3}}, {}}, 0))

运行输出 ​

text
[0 2 5]

完整 Go 示例 ​

go
package main

import "fmt"

type Edge struct{ To, Weight int }

func Dijkstra(g [][]Edge, start int) []int {
	inf := int(^uint(0) >> 1)
	dist := make([]int, len(g))
	used := make([]bool, len(g))
	for i := range dist {
		dist[i] = inf
	}
	dist[start] = 0
	for range g {
		v := -1
		for i := range g {
			if !used[i] && (v < 0 || dist[i] < dist[v]) {
				v = i
			}
		}
		if v < 0 || dist[v] == inf {
			break
		}
		used[v] = true
		for _, e := range g[v] {
			if dist[v]+e.Weight < dist[e.To] {
				dist[e.To] = dist[v] + e.Weight
			}
		}
	}
	return dist
}

func main() {
	fmt.Println(Dijkstra([][]Edge{{{To: 1, Weight: 2}}, {{To: 2, Weight: 3}}, {}}, 0))
}

继续阅读