无向图-邻接表方式
【理论知识可以参考这边】
图论算法——无向图的邻接链表实现_日积月累,天道酬勤-CSDN博客_无向图的邻接链表
图论算法——无向图的深度优先搜索和广度优先搜索_日积月累,天道酬勤-CSDN博客
漫画:图的 “最短路径” 问题_程序员小灰的博客-CSDN博客
【lua实现】
1 local Graph = {} 2 Graph.__index = Graph 3 4 ---无向图 5 function Graph.new() 6 local obj = {} 7 setmetatable(obj, Graph) 8 9 obj:ctor() 10 return obj 11 end 12 13 function Graph:ctor() 14 self.adjacent = {} 15 self.edgeCount = 0 16 self.vertexList = {} 17 end 18 19 function Graph:GetVertexCount() 20 return #self.vertexList 21 end 22 23 function Graph:GetVertex(index) 24 return self.vertexList[index] 25 end 26 27 function Graph:GetEdgeCount() 28 return self.edgeCount 29 end 30 31 function Graph:AddVertex(v) 32 local list = self.adjacent[v] 33 if nil == list then 34 list = {} 35 self.adjacent[v] = list 36 table.insert(self.vertexList, v) 37 else 38 --顶点已存在 39 end 40 end 41 42 function Graph:AddEdge(v1, v2) 43 local list1 = self.adjacent[v1] 44 local list2 = self.adjacent[v2] 45 if nil == list1 or nil == list2 then 46 return --顶点不存在 47 end 48 49 table.insert(list1, v2) --最好判断下在list中是否已存在 50 table.insert(list2, v1) 51 self.edgeCount = self.edgeCount + 1 52 end 53 54 function Graph:GetAdjacent(v) 55 return self.adjacent[v] 56 end 57 58 function Graph:__tostring() 59 print("-----Graph") 60 for i=1,#self.vertexList do 61 local v = self.vertexList[i] 62 local adjList = self.adjacent[v] 63 print(v, "-->", table.concat(adjList, ", ")) 64 end 65 print("-----") 66 end 67 68 return Graph
测试代码:
1 function CreateGraph() 2 local g = Graph.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") 12 g:AddEdge("A", "C") 13 g:AddEdge("B", "D") 14 g:AddEdge("B", "E") 15 g:AddEdge("C", "D") 16 g:AddEdge("C", "F") 17 g:AddEdge("D", "E") 18 g:AddEdge("D", "F") 19 g:AddEdge("E", "G") 20 g:AddEdge("F", "G") 21 22 print("v ct: ", g:GetVertexCount()) 23 print("edge ct:", g:GetEdgeCount()) 24 tostring(g) 25 return g 26 end
上面的代码会创建出这样一张图
【深度优先搜索】
# 这边使用了递归来实现
# 用途:会把某个点的所有可达顶点都走一遍,即可以通过它来确定两个点之间是否可达
1 function TestDfs1() 2 local visited = {} 3 4 function Dfs1(g, vertex) 5 print(vertex) 6 7 visited[vertex] = true 8 local list = g:GetAdjacent(vertex) 9 for i=1,#list do 10 local adjV = list[i] 11 if not visited[adjV] then 12 Dfs1(g, adjV) 13 end 14 end 15 end 16 17 local g = CreateGraph() 18 Dfs1(g, "A") 19 end 20 TestDfs1()
【广度优先搜索】
# 一般会借助一个队列来实现
# 用途1:会把某个点的所有可达顶点都走一遍,即可以知道两个点之间是否可达
# 用途2:可以算出点A到点B的最短路径
1 function TestBfs1() 2 local edgeFrom = {} 3 4 function Bfs1(g, vertex) 5 local visited = {} 6 local queue = {} 7 visited[vertex] = true --加入queue就要设为visited 8 table.insert(queue, vertex) 9 10 while #queue > 0 do 11 local v = queue[1] 12 print("---", table.concat(queue, ", ")) 13 print(v) 14 table.remove(queue, 1) 15 16 local list = g:GetAdjacent(v) 17 for i=1,#list do 18 local adjV = list[i] 19 if not visited[adjV] then 20 visited[adjV] = true --加入queue就要设为visited 21 edgeFrom[adjV] = v 22 table.insert(queue, adjV) 23 end 24 end 25 end 26 end 27 28 local g = CreateGraph() 29 Bfs1(g, "A") 30 31 local path = {} 32 local target = "G" 33 local start = "A" 34 local v = target 35 while v ~= start do 36 table.insert(path, v) 37 v = edgeFrom[v] 38 end 39 table.insert(path, v) 40 print("shortest path: ", table.concat(path)) 41 end 42 TestBfs1()