福大大 答案2021-04-24:
1)在图中找到所有入度为0的点输出。
2)把所有入度为0的点在图中删掉,继续找入度为0的点输出,周而复始。
3)图的所有点都被删除后,依次输出的顺序就是拓扑排序。
要求:有向图且其中没有环。
应用:事件安排、编译顺序。
代码用golang编写。代码如下:
package main import "fmt" func main() { matrix := [][]int{ {0, 1, 1, 0, 0, 0}, {0, 0, 1, 0, 0, 1}, {0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 1, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 0}} graph := NewGraph(matrix) ret := sortedTopology(graph) for i := 0; i < len(ret); i++ { fmt.Print(ret[i].Val, "\t") } } // directed graph and no loop func sortedTopology(graph *Graph) []*Node { // key 某个节点 value 剩余的入度 inMap := make(map[*Node]int) // 只有剩余入度为0的点,才进入这个队列 zeroInQueue := make([]*Node, 0) for _, node := range graph.Nodes { inMap[node] = node.In if node.In == 0 { zeroInQueue = append(zeroInQueue, node) } } result := make([]*Node, 0) for len(zeroInQueue) > 0 { cur := zeroInQueue[len(zeroInQueue)-1] zeroInQueue = zeroInQueue[0 : len(zeroInQueue)-1] result = append(result, cur) for _, next := range cur.Nexts { inMap[next] = inMap[next] - 1 if inMap[next] == 0 { zeroInQueue = append(zeroInQueue, next) } } } return result } type Edge struct { Weight int From *Node To *Node } // 点结构的描述 type Node struct { Val int In int Out int Nexts []*Node Edges []*Edge } type Graph struct { Nodes map[int]*Node Edges map[*Edge]struct{} } //二维数组转成边 func NewGraph(matrix [][]int) *Graph { graph := &Graph{} graph.Nodes = make(map[int]*Node) graph.Edges = make(map[*Edge]struct{}) for i := 0; i < len(matrix); i++ { for j := 0; j < len(matrix[0]); j++ { // 拿到每一条边, matrix[i] weight := matrix[i][j] if weight > 0 { from := i to := j if _, ok := graph.Nodes[from]; !ok { graph.Nodes[from] = &Node{Val: from} } if _, ok := graph.Nodes[to]; !ok { graph.Nodes[to] = &Node{Val: to} } fromNode := graph.Nodes[from] toNode := graph.Nodes[to] newEdge := &Edge{Weight: weight, From: fromNode, To: toNode} fromNode.Nexts = append(fromNode.Nexts, toNode) fromNode.Out++ toNode.In++ fromNode.Edges = append(fromNode.Edges, newEdge) graph.Edges[newEdge] = struct{}{} } } } return graph }
执行结果如下: