dfs检测有向图是否存在环

【lua实现】 

 1 local DfsCheckCycle = {}
 2 DfsCheckCycle.__index = DfsCheckCycle
 3 
 4 function DfsCheckCycle.new(g)
 5     local obj = {}
 6     setmetatable(obj, DfsCheckCycle)
 7 
 8     obj:ctor(g)
 9     return obj
10 end
11 
12 function DfsCheckCycle:ctor(g)
13     self.graph = g
14 
15     self.startVertex = nil
16     self.visited = nil
17     self.visitFromMap = nil
18     self.cycleCheckStack = nil ---每进1层递归设为true, 递归退出设为false
19     self.cyclePath = nil
20 end
21 
22 function DfsCheckCycle:VisitAllReachable(startVertex)
23     self.startVertex = startVertex
24     self.visited = {}
25     self.visitFromMap = {}
26     self.cycleCheckStack = {}
27     self.cyclePath = nil
28 
29     function dfs(v)
30         self.visited[v] = true
31         self.cycleCheckStack[v] = true
32 
33         local list = self.graph:GetAdjacent(v)
34         for i=1,#list do
35             if self:HasCycle() then
36                 break
37             end
38 
39             local adjV = list[i]
40             if not self.visited[adjV] then
41                 self.visitFromMap[adjV] = v
42                 dfs(adjV)
43                 return
44             end
45 
46             if self.cycleCheckStack[adjV] then --发现环, adjV在前面的递归路径上存在
47                 self.cyclePath = {}
48                 local cycleVertex = adjV
49                 local tempV = v
50                 while tempV ~= cycleVertex do --向前找到环的起点
51                     table.insert(self.cyclePath, 1, tempV)
52                     tempV = self.visitFromMap[tempV]
53                 end
54                 table.insert(self.cyclePath, 1, cycleVertex) --发生环的点
55                 table.insert(self.cyclePath, cycleVertex) --回到环的起点
56                 break
57             end
58         end
59 
60         self.cycleCheckStack[v] = false
61     end
62 
63     dfs(startVertex)
64 end
65 
66 function DfsCheckCycle:HasCycle()
67     return nil ~= self.cyclePath
68 end
69 
70 function DfsCheckCycle:PrintCyclePath()
71     if self:HasCycle() then
72         print(table.concat(self.cyclePath, "->"))
73     else
74         print("no cycle")
75     end
76 end

 

测试代码:

 1 function CreateDGraph3()
 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", "1")
11     g:AddEdge("1", "2")
12     g:AddEdge("2", "3")
13     g:AddEdge("3", "1")
14     g:AddEdge("2", "4")
15     g:AddEdge("4", "5")
16 
17     tostring(g)
18     return g
19 end
20 
21 function DfsCheckCycleTest1()
22     local g = CreateDGraph3()
23     local dfsCheckCycle = DfsCheckCycle.new(g)
24     dfsCheckCycle:VisitAllReachable("0")
25     dfsCheckCycle:PrintCyclePath()
26 end
27 DfsCheckCycleTest1()

 

【参考】

环和有向无环图

判断图中是否存在环_秦昊wan-CSDN博客_判断图中是否有环

 

posted @ 2022-03-10 23:45  yanghui01  阅读(100)  评论(0编辑  收藏  举报