Golang 实现 Dijkstra 单源最短路径算法详解

Ada
Ada
发布时间:2026-10-15 | 5人浏览过
原创

本文深入解析如何使用 Golang 实现经典的 Dijkstra 最短路径算法,重点阐述基于邻接矩阵的贪心策略执行流程,并提供包含完整注释的源码及测试用例,助您掌握核心逻辑。

Dijkstra 算法核心逻辑解析

Dijkstra 算法是解决带权有向图或无向图的单源最短路径问题的经典方法。其核心思想采用贪心策略:始终选择当前距离起点最近且未被访问的节点进行扩展,并利用该节点去松弛(更新)其相邻节点的距离值。

第1步:数据结构初始化

算法开始执行前,需要建立维护状态的数据结构。以二维数组(邻接矩阵)表示图时:

  • visited` 数组:布尔类型切片,用于标记节点是否已确认最终最短距离。
  • distance` 数组:整数类型切片,存储起点到各节点的当前已知最短距离。初始状态下,除起点外均设为无穷大(如 math.MaxInt32),起点自身距离设为 0。

第2步:主循环迭代更新

这是算法的核心步骤,重复执行直到所有可达节点被访问:

  1. 寻找最近未访问节点:遍历 visited` 为 false 的所有节点,找到 distance` 值最小的节点作为当前处理节点(Current Node)。
  2. 标记访问状态:将找到的当前节点在 visited` 中标记为 true,表示该节点的最短路径已确定。
  3. 执行松弛操作(Relaxation):遍历当前节点的所有邻居节点。计算“起点到当前节点的距离 + 当前节点到邻居的距离”。若该新距离小于邻居节点当前的 distance` 值,则更新邻居的距离值为更小的新距离。

第3步:返回结果

当循环结束(所有节点被访问或仅剩不可达节点),distance` 数组中存储的值即为起点到其他各节点的最短路径长度。

Golang 完整代码实现

以下代码使用邻接矩阵表示图,其中 -1` 代表两节点间无边相连。该实现严格遵循上述逻辑步骤。

package main

import (
	"fmt"
	"math"
)

// Dijkstra 算法用于计算无向图的最短路径
// graph: 邻接矩阵,-1 表示无连接
// startNode: 起始节点索引
func dijkstra(graph [][]int, startNode int) []int {
	nodesCount := len(graph)
	visited := make([]bool, nodesCount)
	distance := make([]int, nodesCount)

	// 1. 初始化 distance 为最大值,visited 为 false
	for i := 0; i < nodesCount; i++ {
		visited[i] = false
		distance[i] = math.MaxInt32
	}

	// 2. 起点到自身的距离为 0
	distance[startNode] = 0

	// 3. 遍历 nodesCount-1 次,每次找出一个最近节点并更新邻居
	for i := 0; i < nodesCount-1; i++ {
		minDistance := math.MaxInt32
		currentNode := -1

		// 查找距离最小的未访问节点
		for j := 0; j < nodesCount; j++ {
			if !visited[j] && distance[j] < minDistance {
				minDistance = distance[j]
				currentNode = j
			}
		}

		// 如果没有找到可达的未访问节点,提前退出
		if currentNode == -1 {
			break
		}

		// 标记当前节点已访问
		visited[currentNode] = true

		// 更新相邻节点的距离
		for j := 0; j < nodesCount; j++ {
			// 存在边且未被访问时进行松弛
			if graph[currentNode][j] != -1 {
				newDistance := distance[currentNode] + graph[currentNode][j]
				if newDistance < distance[j] {
					distance[j] = newDistance
				}
			}
		}
	}

	return distance
}

func main() {
	// 测试用例:5个节点的无向图
	graph := [][]int{
		{-1, 2, -1, 6, -1},
		{2, -1, 3, 8, 5},
		{-1, 3, -1, -1, 7},
		{6, 8, -1, -1, 9},
		{-1, 5, 7, 9, -1},
	}

	startNode := 0 // 从节点 0 出发
	distances := dijkstra(graph, startNode)

	fmt.Println("Shortest distances from node", startNode, "to all other nodes:")
	for i, d := range distances {
		fmt.Printf("Node %d: %d\n", i, d)
	}
}

结果分析与验证

运行上述代码,程序将从控制台输出每个节点相对于起点(节点 0)的最短距离:

  • Node 0 → Node 0: 0
  • Node 0 → Node 1: 2 (直接连接)
  • Node 0 → Node 2: 5 (路径: 0→1→2,距离 2+3=5)
  • Node 0 → Node 3: 6 (直接连接)
  • Node 0 → Node 4: 7 (路径: 0→1→4,距离 2+5=7,优于 0→3→4 的 6+9)

注意事项与优化空间

  • 无权/负权限制:Dijkstra 算法要求图中所有边的权重非负。若存在负权边,请使用 Bellman-Ford 算法。
  • 性能瓶颈:上述实现使用的是简单线性搜索来寻找最小距离节点,时间复杂度为 $O(V^2)$,适合稠密图。对于稀疏图,建议优先队列(堆)优化,将复杂度降至 $O(E imes \log V)$。
  • 邻接矩阵 vs 邻接表:若图节点数极多但连接稀疏,改用 map[int][]Edge` 结构的邻接表可以显著节省内存并提升遍历效率。
以上就是 Golang 实现 Dijkstra 算法过程的详细内容,更多关于 Go 语言最短路径计算的资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表