使用 Golang 实现 Bellman-Ford 算法的程序


Bellman-Ford 算法是一种图遍历方法,用于在加权网络中查找从特定顶点到所有顶点的最短距离。在本文中,我们将编写一个 Go 语言程序来实现 Bellman-Ford 算法。此算法用于处理需要在加权有向图中查找从源顶点到其他顶点的最短路径的情况。它通过在找到最短路径时更新顶点的距离值来工作。

语法

func make ([] type, size, capacity)

Go 语言中的 **make** 函数用于创建数组/映射,它接受要创建的变量类型、其大小和容量作为参数。

func append(slice, element_1, element_2…, element_N) []T

append 函数用于向数组切片添加值。它接受多个参数。第一个参数是要添加值的数组,后跟要添加的值。然后,该函数返回包含所有值的最终数组切片。

func len(v Type) int

len() 函数用于获取任何参数的长度。它将要查找长度的数据类型变量作为参数,并返回表示变量长度的整数值。

算法

  • **步骤 1** - 创建一个 Edge 结构体来表示图中的边,它包含三个字段:源 (source,类型为 int),目标 (destination,类型为 int) 和权重 (weight,类型为 float)。

  • **步骤 2** - 然后,创建一个 Graph 结构体来表示加权有向图,它包含两个字段:顶点数 (number of vertices,类型为 int) 和边切片 (edges)。

  • **步骤 3** - 创建一个 BellmanFord() 函数,它以图和源顶点作为输入,并返回距离数组和前驱顶点数组。

  • **步骤 4** - 然后,初始化所有顶点的距离数组 (dist[]) 和前驱顶点数组 (prev[])。检查是否存在负权回路,即 dist[u] + w 是否小于 dist[v]。

  • **步骤 5** - 创建一个 PrintShortestPaths() 函数,它打印从源顶点到所有其他顶点的最短路径。

  • **步骤 6** - 然后,通过遍历从起始点开始的前驱顶点数组来构造最短路径,并打印距离和路径。创建 main 函数并初始化源顶点为 0。

  • **步骤 7** - 最后,执行 Bellman-Ford 算法并获取距离和前驱顶点数组,如果数组不为空,则打印从源顶点的最短路径。

示例

在本文中,我们将编写一个 Go 语言程序来实现 Bellman-Ford 算法,以在加权有向图中查找最短路径。

package main

import (
   "fmt"
   "math"
)
type Edge struct {
   src    int     
   dest   int     
   weight float64 
}
type Graph struct {
   vertices int   
   edges    []Edge 
}
func InitGraph(vertices int) *Graph {
   return &Graph{
      vertices: vertices,
      edges:    make([]Edge, 0),
   }
}
func (g *Graph) AddEdge(src, dest int, weight float64) {
   g.edges = append(g.edges, Edge{src, dest, weight})
}
func BellmanFord(g *Graph, source int) ([]float64, []int) {
   dist := make([]float64, g.vertices) 
   prev := make([]int, g.vertices)     
   for i := 0; i < g.vertices; i++ {
      dist[i] = math.Inf(1) 
      prev[i] = -1        
   }
   dist[source] = 0 
  
   for i := 1; i < g.vertices; i++ {
      for _, edge := range g.edges {
         u := edge.src
         v := edge.dest
         w := edge.weight
         if dist[u]+w < dist[v] {
            dist[v] = dist[u] + w
            prev[v] = u
         }
      }
   }

   for _, edge := range g.edges {
      u := edge.src
      v := edge.dest
      w := edge.weight
      if dist[u]+w < dist[v] {
         fmt.Println("Graph contains a negative weight cycle")
         return nil, nil
      }
   }

   return dist, prev
}

func PrintShortestPaths(dist []float64, prev []int, source int) {
   fmt.Println("Shortest Paths from vertex", source)
   for i := 0; i < len(dist); i++ {
      if dist[i] == math.Inf(1) {
         fmt.Printf("Vertex %d is not reachable\n", i)
      } else {
         path := []int{}
         j := i
         for j != -1 {
            path = append([]int{j}, path...)
            j = prev[j]
         }
         fmt.Printf("Vertex %d: Distance=%f, Path=%v\n", i, dist[i], path)
      }
   }
}

func main() {
   g := InitGraph(5)

   g.AddEdge(0, 1, 6)
   g.AddEdge(0, 2, 7)
   g.AddEdge(1, 2, 8)
   g.AddEdge(1, 3, -4)
   g.AddEdge(1, 4, 5)
   g.AddEdge(2, 3, 9)
   g.AddEdge(2, 4, -3)
   g.AddEdge(3, 1, 7)
   g.AddEdge(4, 0, 2)
   g.AddEdge(4, 3, 7)

   source := 0
   dist, prev := BellmanFord(g, source)
   if dist != nil && prev != nil {
      PrintShortestPaths(dist, prev, source)
   }
}

输出

Shortest Paths from vertex 0
Vertex 0: Distance=0.000000, Path=[0]
Vertex 1: Distance=6.000000, Path=[0 1]
Vertex 2: Distance=7.000000, Path=[0 2]
Vertex 3: Distance=2.000000, Path=[0 1 3]
Vertex 4: Distance=4.000000, Path=[0 2 4]

结论

在本文中,我们使用结构体执行了实现 Bellman-Ford 算法的程序。我们探讨了此算法的工作原理,还了解了如何使用邻接表表示图。

更新于: 2023-07-05

241 次查看

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告