有向图-邻接表方式

 【理论知识可以参考这边】

有向图的邻接链表实现

有向图的可达性与寻路

 

【lua实现】

 1 local DGraph = {}
 2 DGraph.__index = DGraph
 3 
 4 function DGraph.new()
 5     local obj = {}
 6     setmetatable(obj, DGraph)
 7 
 8     obj:ctor()
 9     return obj
10 end
11 
12 function DGraph:ctor()
13     self.adjacent = {}
14     self.edgeCount = 0
15 
16     self.vertexList = {}
17 end
18 
19 function DGraph:GetVertexCount()
20     return #self.vertexList
21 end
22 
23 function DGraph:GetEdgeCount()
24     return self.edgeCount
25 end
26 
27 function DGraph:AddVertex(v)
28     local list = self.adjacent[v]
29     if nil == list then
30         list = {}
31         self.adjacent[v] = list
32         table.insert(self.vertexList, v)
33     end
34 end
35 
36 function DGraph:AddEdge(v1, v2)
37     local list1 = self.adjacent[v1]
38     local list2 = self.adjacent[v2]
39     if nil == list1 or nil == list2 then
40         --顶点不存在
41         return
42     end
43     table.insert(list1, v2)
44 end
45 
46 function DGraph:__tostring()
47     print("-----DGraph")
48     for i=1,#self.vertexList do
49         local v = self.vertexList[i]
50         local list = self.adjacent[v]
51         print(v, "-->", table.concat(list, ", "))
52     end
53     print("-----")
54 end

 测试代码

 1 function CreateDGraph()
 2     local g = DGraph.new()
 3     g:AddVertex("0")
 4     g:AddVertex("1")
 5     g:AddVertex("2")
 6     g:AddVertex("3")
 7     g:AddVertex("4")
 8     g:AddVertex("5")
 9 
10     g:AddEdge("0", "2")
11     g:AddEdge("2", "0")
12     g:AddEdge("2", "1")
13     g:AddEdge("2", "3")
14     g:AddEdge("3", "2")
15     g:AddEdge("3", "4")
16     g:AddEdge("3", "5")
17 
18     print(g:GetEdgeCount())
19     print(g:GetVertexCount())
20     tostring(g)
21 end
22 CreateDGraph()

 

【深度优先搜索dfs和广度优先搜索bfs】

# dfs和bfs都可以知道是否可达

# dfs和bfs都可以获取两点之间的路径, 但bfs的路径是最短路径

 1 local Dfs = {}
 2 Dfs.__index = Dfs
 3 
 4 function Dfs.new(g)
 5     local obj = {}
 6     setmetatable(obj, Dfs)
 7 
 8     obj:ctor(g)
 9     return obj
10 end
11 
12 function Dfs:ctor(g)
13     if nil == g then
14         print("ctor g nil")
15     end
16     self.graph = g
17     self.startVertex = nil
18     self.visited = {}
19     self.visitFromMap = {} --通过目标点获取访问源点
20 end
21 
22 ---到另一个点是否可达
23 function Dfs:IsReachable(endVertex)
24     return true == self.visited[endVertex]
25 end
26 
27 ---遍历所有可达的顶点
28 function Dfs:VisitAllReachable(startVertex)
29     self.startVertex = startVertex
30     self.visited = {}
31     self.visitFromMap = {}
32 
33     function dfs(v)
34         self.visited[v] = true
35 
36         local list = self.graph:GetAdjacent(v)
37         for i=1,#list do
38             local adjV = list[i]
39             if not self.visited[adjV] then
40                 self.visitFromMap[adjV] = v
41                 dfs(adjV)
42             end
43         end
44     end
45 
46     dfs(startVertex)
47 end
48 
49 ---两个点之间的路径
50 function Dfs:GetPath(endVertex)
51     if not self:IsReachable(endVertex) then return nil end
52 
53     local pathQueue = {}
54     --从目标点, 反向一步一步算出起点
55     local v = endVertex
56     while v ~= self.startVertex do
57         table.insert(pathQueue, 1, v)
58         v = self.visitFromMap[v]
59     end
60     table.insert(pathQueue, 1, v)
61     return pathQueue
62 end

测试代码

1 function TestDfs1()
2     local g = CreateDGraph()
3     local dfs = Dfs.new(g)
4     dfs:VisitAllReachable("3")
5     print(dfs:IsReachable("4"))
6     print(dfs:IsReachable("0"))
7     print(table.concat(dfs:GetPath("4"), "->"))
8 end
9 TestDfs1()

 

【广度优先搜索】

 1 local Bfs = {}
 2 Bfs.__index = Bfs
 3 
 4 function Bfs.new(g)
 5     local obj = {}
 6     setmetatable(obj, Bfs)
 7 
 8     obj:ctor(g)
 9     return obj
10 end
11 
12 function Bfs:ctor(g)
13     self.graph = g
14     self.startVertex = nil
15     self.visited = {}
16     self.visitFrom = {} --从哪个点访问的key对应的点
17 end
18 
19 function Bfs:IsReachable(endVertex)
20     return true == self.visited[endVertex]
21 end
22 
23 function Bfs:VisitAllReachable(startVertex)
24     self.startVertex = startVertex
25     self.visited = {}
26     self.visitFrom = {}
27 
28     local queue = {}
29     self.visited[startVertex] = true
30     table.insert(queue, startVertex)
31 
32     while #queue > 0 do
33         local v = queue[1]
34         table.remove(queue, 1)
35 
36         local list = self.graph:GetAdjacent(v)
37         for i=1,#list do
38             local adjV = list[i]
39             if not self.visited[adjV] then
40                 self.visitFrom[adjV] = v
41                 self.visited[adjV] = true
42                 table.insert(queue, adjV)
43             end
44         end
45     end
46 end
47 
48 function Bfs:GetPath(endVertex)
49     if not self:IsReachable(endVertex) then return nil end
50 
51     local pathQueue = {}
52     local v = endVertex
53     while v ~= self.startVertex do
54         table.insert(pathQueue, 1, v)
55         v = self.visitFrom[v]
56     end
57     table.insert(pathQueue, 1, v)
58     return pathQueue
59 end

测试代码

 1 function CreateDGraph2()
 2     local g = DGraph.new()
 3     g:AddVertex("0")
 4     g:AddVertex("1")
 5     g:AddVertex("2")
 6     g:AddVertex("3")
 7     g:AddVertex("4")
 8     g:AddVertex("5")
 9 
10     g:AddEdge("0", "2")
11     g:AddEdge("2", "0")
12     g:AddEdge("2", "1")
13     g:AddEdge("2", "3")
14     g:AddEdge("2", "5")
15     g:AddEdge("3", "2")
16     g:AddEdge("3", "4")
17     g:AddEdge("3", "5")
18 
19     return g
20 end
21 
22 function TestBfs1()
23     local g = CreateDGraph2()
24 
25     local dfs = Bfs.new(g)
26     dfs:VisitAllReachable("0")
27     print(dfs:IsReachable("3"))
28     print(dfs:IsReachable("5"))
29     print(table.concat(dfs:GetPath("5"), "->"))
30 end
31 TestBfs1()

 

上一篇:ubuntu20.04笔记


下一篇:刨析Django----邮件激活