Do you have a solid algorithmic approach how to tackle topological sort? There are different possibilities; the two best-known are probably the following:
Do a DFS on the graph and sort the vertices according to their finish time in descending order. So: If you already have DFS, adapt it do output finish times and sort vertices in descending order.
The other approach requires you to store the number of incoming, not-yet-processed edges into each vertex (this possibly requires some preprocessing, usually one graph traversal - let's call the corresponding field for each vertex the "edge counter"). Starting nodes - of course - have edge counter = 0. As the next vertex, you can only pick those whose edge counter is set to 0. If you encounter an edge
(a,b,w)
, you have to decrement the edge counter ofb
by 1.Note that this second approach can be implemented in a way such you have a list
candidates
that is initially only filled with the starting nodes. As soon as you decrement the edge counter ofb
and see that it is now 0, you addb
to thecandidates
. In the next step, you pick the head ofcandidates
as the next vertex to process.To store the edge count, you could use e.g. a HashMap.
Here some (non-haskell, but probably-close-to-haskell) inspiration for the second approach:
sortAlgorithm startingNodes sorted (Graph v w) edgeCounts =
| [] _ _ = sorted -- processed all nodes? => output result
| (x:remainingNodes) sorted (Graph v w) =
let newEdgeCounts = foldl
(\ec (a, b, w) -> Data.HashMap.insert ((Data.HashMap.findWithDefault 0 b ec) - 1) ec)
in sortAlgorithm remainingNodes (sorted ++ [x]) newEdgeCounts