Extracted from here we got a minimal iterative dfs routine, i call it minimal because you can hardly simplify the code further:
def iterative_dfs(graph, star
My idea is based on two key observations:
Both of these help us to traverse the graph exactly like recursive dfs. As the other answer here noted, this is important for this particular problem. The rest should be easy.
def iterative_topological_sort(graph, start,path=set()):
q = [start]
ans = []
while q:
v = q[-1] #item 1,just access, don't pop
path = path.union({v})
children = [x for x in graph[v] if x not in path]
if not children: #no child or all of them already visited
ans = [v]+ans
q.pop()
else: q.append(children[0]) #item 2, push just one child
return ans
q
here is our stack. In the main loop, we 'access' our current node v
from the stack. 'access', not 'pop', because we need to be able to come back to this node again. We find out all unvisited children of our current node. and push only the first one to stack (q.append(children[0])
), not all of them together. Again, this is precisely what we do with recursive dfs.
If no eligible child is found (if not children
), we have visited the entire subtree under it. So it's ready to be pushed into ans
. And this is when we really pop it.
(Goes without saying, it's not great performance-wise. Instead of generating all unvisited children in children
variable, we should just generate the first one, generator style, maybe using filter. We should also reverse that ans = [v] + ans
and call a reverse
on ans
at the end. But these things are omitted for OP's insistence on simplicity.)