github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/topology/topo.go (about) 1 package topology 2 3 import ( 4 "fmt" 5 "github.com/qiuhoude/go-web/algorithm/datastructures/queue" 6 "github.com/qiuhoude/go-web/algorithm/datastructures/stack" 7 ) 8 9 /* 10 11 拓扑排序中 12 1. kahn算法 13 2. DFS算法 14 15 比如 依赖关系 (箭头表示 xx 依赖 xxx ) A->B , B->C ,C->D 16 求出依赖关系 17 使用 有向图 的数据结构进行处理 18 19 */ 20 21 // 顶点 22 type vertex struct { 23 id int 24 v interface{} 25 } 26 27 func (v *vertex) String() string { 28 return fmt.Sprintf("(%v, %v)", v.id, v.v) 29 } 30 31 func newVertex(id int, v interface{}) *vertex { 32 return &vertex{ 33 id: id, 34 v: v, 35 } 36 } 37 38 // 边 39 type edge struct { 40 sid int // 起点id 41 tid int // 目标id 42 //weight int // 权重 43 } 44 45 func newEdge(sid, tid int) *edge { 46 return &edge{ 47 sid: sid, 48 tid: tid, 49 } 50 } 51 52 // 有向图 53 type Graph struct { 54 adj map[int]*vertex 55 edges map[int][]*edge // [顶点起点id] 56 } 57 58 func NewGraph() *Graph { 59 return &Graph{ 60 adj: make(map[int]*vertex), 61 edges: make(map[int][]*edge), 62 } 63 } 64 65 // 添加顶点 66 func (g *Graph) AddVertex(id int, v interface{}) { 67 if !g.ContainsVertex(id) { 68 g.adj[id] = newVertex(id, v) 69 } 70 } 71 func (g *Graph) ContainsVertex(id int) bool { 72 _, ok := g.adj[id] 73 return ok 74 } 75 76 func (g *Graph) ContainsEdge(sid, tid int) bool { 77 if eds, ok := g.edges[sid]; ok { 78 for i := range eds { 79 if tid == eds[i].tid { 80 return true 81 } 82 } 83 } 84 return false 85 } 86 87 // 添加边 88 func (g *Graph) AddEdge(sid, tid int) { 89 if g.ContainsVertex(sid) && g.ContainsVertex(tid) && sid != tid { 90 if !g.ContainsEdge(sid, tid) { 91 eds := g.edges[sid] 92 eds = append(eds, newEdge(sid, tid)) 93 g.edges[sid] = eds 94 } 95 } 96 } 97 98 //拓扑排序中的 Kahn 算法 O(V+E)(V 表示顶点个数,E 表示边的个数) 99 func topoSortKahn(g *Graph) []interface{} { 100 // 统计顶点入度 101 inDegree := make(map[int]int) 102 for id := range g.adj { 103 inDegree[id] = 0 104 } 105 for id := range g.adj { 106 if eds, ok := g.edges[id]; ok { 107 for i := range eds { 108 inDegree[eds[i].tid]++ 109 } 110 } 111 } 112 que := queue.NewLinkedQueue() 113 for i := range inDegree { 114 if inDegree[i] == 0 { // 入度是0的添加进队列 115 que.Enqueue(i) 116 } 117 } 118 st := stack.NewArrayStack() 119 for !que.IsEmpty() { 120 id := que.Dequeue().(int) 121 st.Push(g.adj[id].v) 122 //fmt.Print("->", g.adj[id]) 123 for _, v := range g.edges[id] { 124 inDegree[v.tid]-- // 125 if inDegree[v.tid] == 0 { 126 que.Enqueue(v.tid) 127 } 128 } 129 } 130 if st.Len() < len(g.adj) { 131 fmt.Println("有环图") 132 } 133 return st.ToSlice() 134 } 135 136 // DFS方式排序 时间复杂度 O(V+E) 137 func topoSortDFS(g *Graph) { 138 // 创建逆邻接表 139 inverseAdj := make(map[int][]int, len(g.adj)) 140 // 填充逆邻接表 141 for _, eds := range g.edges { 142 for i := range eds { 143 e := eds[i] 144 inverseAdj[e.tid] = append(inverseAdj[e.tid], e.sid) 145 } 146 } 147 visited := make(map[int]bool) // 访问记录 148 for v := range g.adj { 149 if !visited[v] { 150 visited[v] = true 151 dfs(v, inverseAdj, visited, g) 152 } 153 } 154 fmt.Println() 155 } 156 157 func dfs(vertex int, inverseAdj map[int][]int, visited map[int]bool, g *Graph) { 158 tids := inverseAdj[vertex] 159 for i := 0; i < len(tids); i++ { 160 tid := tids[i] 161 if visited[tid] { 162 continue 163 } 164 visited[tid] = true 165 dfs(tid, inverseAdj, visited, g) 166 } 167 fmt.Print("->", g.adj[vertex].v) 168 }