@@ -128,14 +128,22 @@ def _find_cycles(graph):
128128 def dfs (v ):
129129 color [v ] = GREY
130130 path .append (v )
131- for w in graph .get (v , ()):
132- if color [w ] == WHITE :
133- dfs (w )
134- elif color [w ] == GREY : # back-edge → cycle!
135- i = path .index (w )
136- cycles .append (path [i :] + [w ]) # make a copy
137- color [v ] = BLACK
138- path .pop ()
131+ stack = [(v , iter (graph .get (v , ())))]
132+ while stack :
133+ v , children = stack [- 1 ]
134+ for w in children :
135+ if color [w ] == WHITE :
136+ color [w ] = GREY
137+ path .append (w )
138+ stack .append ((w , iter (graph .get (w , ()))))
139+ break
140+ elif color [w ] == GREY : # back-edge → cycle!
141+ i = path .index (w )
142+ cycles .append (path [i :] + [w ]) # make a copy
143+ else :
144+ color [v ] = BLACK
145+ path .pop ()
146+ stack .pop ()
139147
140148 for v in list (graph ):
141149 if color [v ] == WHITE :
@@ -167,14 +175,16 @@ def pretty(node):
167175 flag = task_emoji if node [0 ] == NodeType .TASK else cor_emoji
168176 return f"{ flag } { labels [node ]} "
169177
170- def render (node , prefix = "" , last = True , buf = None ):
171- if buf is None :
172- buf = []
173- buf .append (f"{ prefix } { '└── ' if last else '├── ' } { pretty (node )} " )
174- new_pref = prefix + (" " if last else "│ " )
175- kids = children .get (node , [])
176- for i , kid in enumerate (kids ):
177- render (kid , new_pref , i == len (kids ) - 1 , buf )
178+ def render (root ):
179+ buf = []
180+ stack = [(root , "" , True )]
181+ while stack :
182+ node , prefix , last = stack .pop ()
183+ buf .append (f"{ prefix } { '└── ' if last else '├── ' } { pretty (node )} " )
184+ new_pref = prefix + (" " if last else "│ " )
185+ kids = children .get (node , [])
186+ for i , kid in reversed (list (enumerate (kids ))):
187+ stack .append ((kid , new_pref , i == len (kids ) - 1 ))
178188 return buf
179189
180190 return [render (root ) for root in _roots (labels , children )]
0 commit comments