diff --git a/container/graph/topo.go b/container/graph/topo.go new file mode 100644 index 0000000..d64abf6 --- /dev/null +++ b/container/graph/topo.go @@ -0,0 +1,41 @@ +package sort + +// Node is a generic interface representing a graph node. +type Node[T any] interface { + // Value returns the value of the node. + Value() T + // Adjacencies returns a slice of nodes adjacent to this node + Adjacencies() []Node[T] +} + +// Topo performs a topological sort on a slice of nodes in place. +func TopoSort[T any](nodes []Node[T]) { + v := make(map[Node[T]]bool) + pos := 0 + var dfs func(Node[T]) + dfs = func(n Node[T]) { + v[n] = true + for _, e := range n.Adjacencies() { + if !v[e] { + dfs(e) + } + } + nodes[pos] = n + pos++ + } + + for _, n := range nodes { + if !v[n] { + dfs(n) + } + } +} + +// RTopoSort performs a reverse topological sort on a slice of nodes in place. +func RTopoSort[T any](nodes []Node[T]) { + TopoSort(nodes) + + for i, j := 0, len(nodes)-1; i < j; i, j = i+1, j-1 { + nodes[i], nodes[j] = nodes[j], nodes[i] + } +}