Skip to content

Commit c462500

Browse files
committedMay 16, 2018
add directed_cycle.py
1 parent c48fa37 commit c462500

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed
 

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Try to keep the interface and variable name consistent with the original book wh
6262
* [DegreesOfSeparation](algs4/degrees_of_separation.py)
6363
* [Digraph](algs4/digraph.py)
6464
* [DirectedDFS](algs4/directed_dfs.py)
65+
* [DirectedCycle](algs4/directed_cycle.py)
6566

6667
* 5 STRING
6768

‎algs4/directed_cycle.py

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
Execution: python directed_cycle.py input.txt
3+
Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
4+
https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt
5+
6+
Finds a directed cycle in a digraph.
7+
Runs in O(E + V) time.
8+
9+
% python directed_cycle.py tinyDG.txt
10+
Directed cycle: 3 5 4 3
11+
12+
% python directed_cycle.py tinyDAG.txt
13+
No directed cycle
14+
15+
"""
16+
from algs4.stack import Stack
17+
from algs4.digraph import Digraph
18+
19+
20+
class DirectedCycle:
21+
22+
def __init__(self, G):
23+
self._marked = [False for _ in range(G.V)]
24+
self.edge_to = [False for _ in range(G.V)]
25+
self.on_stack = [False for _ in range(G.V)]
26+
self.cycle = None
27+
for v in range(G.V):
28+
if not self._marked[v]:
29+
self.dfs(G, v)
30+
31+
def dfs(self, G, v):
32+
self._marked[v] = True
33+
self.on_stack[v] = True
34+
35+
for w in G.adj[v]:
36+
if self.has_cycle():
37+
return
38+
if not self._marked[w]:
39+
self.edge_to[w] = v
40+
self.dfs(G, w)
41+
elif self.on_stack[w]:
42+
self.cycle = Stack()
43+
x = v
44+
while x != w:
45+
self.cycle.push(x)
46+
x = self.edge_to[x]
47+
self.cycle.push(w)
48+
self.cycle.push(v)
49+
self.on_stack[v] = False
50+
51+
def marked(self, v):
52+
return self._marked[v]
53+
54+
def has_cycle(self):
55+
return self.cycle is not None
56+
57+
if __name__ == '__main__':
58+
import sys
59+
f = open(sys.argv[1])
60+
V = int(f.readline())
61+
E = int(f.readline())
62+
g = Digraph(V)
63+
for i in range(E):
64+
v, w = f.readline().split()
65+
g.add_edge(v, w)
66+
67+
finder = DirectedCycle(g)
68+
if finder.has_cycle():
69+
for v in finder.cycle:
70+
print(v, end=" ")
71+
else:
72+
print("No directed cycle")

0 commit comments

Comments
 (0)
Please sign in to comment.