跳到主要内容

Topological sort

Description

Topological sort只可以用在DAG (directed acyclic graph)上面,而graph節點之間為partial order。可以適用於任務排程等工作。

Pseudo code

TOPOLOGICAL SORT(G)
1. call DFS(G) to compute finish times v.f for each vertex v
2. as each vertex is finished, insert it onto the fronend of a linked list
return the linked list of verticies

Time complexity

Θ\Theta(V+EV + E)。

因為DFS走訪過所有的vertices和edges,然後linked list的長度為VV

Proofs

Lemma 1

Statement: A directed graph GG is acyclic if and only if a depth-first search of GG yields no back edges

Proof:

利用反證法可以證明此lemmalemma,存在edge (u,v)(u, v)是一個back edge,代表v是u的祖先(ancestor),因此存在一個路徑PP,使得vv -> uu ,但又已知存在一個back edge (u,v)(u, v)行程迴圈,因此與假設矛盾,故不存在 back edge (u,v)(u, v)

反過來證明如果 DFSDFS(GG)不產生back edge,則GG is acyclic。因為GG不存在back edge,如果u.finishu.finish > v.finishv.finish,則uu 必定在vv 之前被探訪,在vv之後完成,因此不產生cycle。

Theorm 1

Statement: TOPOLOGICAL-SORT produces a topological sort of the directed acyclic graph provided as its input

Proof:

根據lemma 1,acyclic graph GG不產生back edge,所以如果v.finishv.finish > u.finishu.finish,代表vvuu之前被探訪,並在uu之後完成探訪,因此它在linked list的位置在uu之前,滿足topological sort的要求。

Golang implementation

topologicalsort.go
import "fmt"

type Vertex struct {
finished bool
}

type Graph struct {
edges map[int][]int
vertices []Vertex
}

func dfsUtil(g Graph, vIdx int, result []Vertex) []Vertex {
edges := g.edges[vIdx]

// visit all
for _, idx := range edges {
if !g.vertices[idx].finished {
result = dfsUtil(g, idx, result)
}
}

g.vertices[vIdx].finished = True
result = append([]Vertex{g.vertices[vIdx], result...})

return result
}

func TopologicalSort(g Graph) []Vertex {
result := []Vertex{}

for i, v := range vertices {
if !v.finished {
result = dfsUtil(g, i, result)
}
}

return result
}