Dijkstra计算加权无向图的最短路径

【理论知识的,可以参考】

漫画:图的最短路径问题

最短路径算法

 

该算法得到的是单源最短路径,即起点到任意目标点的距离

【lua实现】

 1 local Dijkstra = {}
 2 Dijkstra.__index = Dijkstra
 3 
 4 function Dijkstra.new(g)
 5     local obj = {}
 6     setmetatable(obj, Dijkstra)
 7 
 8     obj:ctor(g)
 9     return obj
10 end
11 
12 function Dijkstra:ctor(g)
13     self.graph = g
14     self.startVertex = nil
15     self.visitFrom = {} --点之间的遍历关系, key:当前遍历点, value:上一个遍历点
16     self.distFromStart = {} --从起始点到该点的距离
17 end
18 
19 function Dijkstra:IsReachable(endVertex)
20     return self.distFromStart[endVertex].dist < 9999
21 end
22 
23 function Dijkstra:VisitAllReachable(startVertex)
24     self.startVertex = startVertex
25     self.visitFrom = {}
26     self.distFromStart = {}
27 
28     for i=1,self.graph:GetVertexCount() do
29         local v = self.graph:GetVertex(i)
30         self.distFromStart[v] = {
31             dist = 9999,
32             used = false,
33         }
34     end
35 
36     local distInfo = self.distFromStart[startVertex]
37     distInfo.dist = 0
38     distInfo.used = true
39 
40     local v = startVertex
41     while true do
42         local adjList = self.graph:GetAdjacent(v)
43         for i=1,#adjList do
44             local adjVInfo = adjList[i]
45             local oldDist = self.distFromStart[adjVInfo.v].dist
46             local newDist = self.distFromStart[v].dist + adjVInfo.w
47             if newDist < oldDist then
48                 self.distFromStart[adjVInfo.v].dist = newDist
49                 self.visitFrom[adjVInfo.v] = v
50             end
51         end
52 
53         --从距离最小的点继续往后遍历
54         --从ta开始过1次, 后面将不会再从ta开始
55         local minDistInfo = nil
56         local minV = nil
57         for i=1,self.graph:GetVertexCount() do
58             local v = self.graph:GetVertex(i)
59             local distInfo = self.distFromStart[v]
60             if not distInfo.used then
61                 if nil == minDistInfo or distInfo.dist < minDistInfo.dist then
62                     minDistInfo = distInfo
63                     minV = v
64                 end
65             end
66         end
67         if nil == minDistInfo then --所有都遍历过了
68             break
69         end
70 
71         minDistInfo.used = true
72         v = minV
73     end
74 end
75 
76 function Dijkstra:GetDist(endVertex)
77     return self.distFromStart[endVertex].dist
78 end
79 
80 function Dijkstra:GetPath(endVertex)
81     if not self:IsReachable(endVertex) then return nil end
82 
83     local pathQueue = {}
84     local v = endVertex
85     while v ~= self.startVertex do
86         table.insert(pathQueue, 1, v)
87         v = self.visitFrom[v]
88     end
89     table.insert(pathQueue, 1, v)
90     return pathQueue
91 end

 

计算下面这张图的最短路径:

Dijkstra计算加权无向图的最短路径

 

 

 

 1 function CreateGraph()
 2     local g = WeightedGraph.new()
 3     g:AddVertex("A")
 4     g:AddVertex("B")
 5     g:AddVertex("C")
 6     g:AddVertex("D")
 7     g:AddVertex("E")
 8     g:AddVertex("F")
 9     g:AddVertex("G")
10 
11     g:AddEdge("A", "B", 5)
12     g:AddEdge("A", "C", 2)
13     g:AddEdge("B", "D", 1)
14     g:AddEdge("B", "E", 6)
15     g:AddEdge("C", "D", 6)
16     g:AddEdge("C", "F", 8)
17     g:AddEdge("D", "E", 1)
18     g:AddEdge("D", "F", 2)
19     g:AddEdge("E", "G", 7)
20     g:AddEdge("F", "G", 3)
21 
22     --tostring(g)
23     return g
24 end
25 
26 function Test1()
27     local g = CreateGraph()
28     local d = Dijkstra.new(g)
29     d:VisitAllReachable("A")
30     assert(d:IsReachable("B"))
31     assert(d:IsReachable("G"))
32 
33     assert(5 == d:GetDist("B"))
34     assert(2 == d:GetDist("C"))
35     assert(6 == d:GetDist("D"))
36     assert(7 == d:GetDist("E"))
37     assert(8 == d:GetDist("F"))
38     assert(11 == d:GetDist("G"))
39 end
40 Test1()

 

上一篇:初识PO模式并在Selenium中简单实践


下一篇:Cannot read properties of undefined (reading ‘target‘)