

golang有向无环图(dag)以及判断是否有环
source link: https://blog.csdn.net/oqqYuan1234567890/article/details/104723305
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

有向无环图 邻接表实现
package main
import (
"fmt"
"github.com/eapache/queue"
)
// 邻接表
type Vertex struct {
Key string
Parents []*Vertex
Children []*Vertex
Value interface{}
}
type DAG struct {
Vertexes []*Vertex
}
func (dag *DAG) AddVertex(v *Vertex) {
dag.Vertexes = append(dag.Vertexes, v)
}
func (dag *DAG) AddEdge(from, to *Vertex) {
from.Children = append(from.Children, to)
to.Parents = append(from.Parents, from)
}
func (dag *DAG) BFS(root *Vertex) {
q := queue.New()
visitMap := make(map[string]bool)
visitMap[root.Key] = true
q.Add(root)
for {
if q.Length() == 0 {
fmt.Println("done")
break
}
current := q.Remove().(*Vertex)
fmt.Println("bfs key", current.Key)
for _, v := range current.Children {
fmt.Printf("from:%v to:%s\n", current.Key, v.Key)
if v.Key == root.Key {
panic("back root")
}
if _, ok := visitMap[v.Key]; !ok {
visitMap[v.Key] = true
//fmt.Println("add visit", v.Key)
q.Add(v)
}
}
}
}
func (dag *DAG) DFS(root *Vertex) {
stack := []*Vertex{root}
visitMap := make(map[string]bool)
visitMap[root.Key] = true
for i := 0; i < 10; i++ {
if len(stack) == 0 {
fmt.Println("done")
break
}
if len(stack)-1 < 0 {
panic("unexpected")
}
current := stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Println("dfs key", current.Key)
for _, v := range current.Children {
fmt.Println("from:%v to:%s", current.Key, v.Key)
if v.Key == root.Key {
panic("back root")
}
if _, ok := visitMap[v.Key]; !ok {
visitMap[v.Key] = true
//fmt.Println("add visit", v.Key)
if v.Key == root.Key {
panic("back root")
}
stack = append(stack, v)
}
}
}
}
func main() {
dag := &DAG{}
v1 := &Vertex{Key: "1"}
v2 := &Vertex{Key: "2"}
v3 := &Vertex{Key: "3"}
v4 := &Vertex{Key: "4"}
v5 := &Vertex{Key: "5"}
// dag
// 5
// >
// /
// 1----->2
// \ > \
// > / >
// 3-------->4
dag.AddEdge(v1, v5)
dag.AddEdge(v1, v2)
//dag.AddEdge(v2, v1)
dag.AddEdge(v1, v3)
dag.AddEdge(v3, v4)
dag.AddEdge(v3, v2)
dag.AddEdge(v2, v4)
dag.BFS(v1)
//dag.DFS(v1)
}
这里要说明一下,对于邻接表的数据结构,千万不要用json来序列化,因为邻接表的实现是有pointer loop问题的,而json包不会检查pointer loop
判断是否有环
一般来说,如果root顶点随着遍历如果会回到自身,那么这个图就是有环的,上面的例子
稍微改动一下
package main
import (
"fmt"
"github.com/eapache/queue"
)
// 邻接表
type Vertex struct {
Key string
Parents []*Vertex
Children []*Vertex
Value interface{}
}
type DAG struct {
Vertexes []*Vertex
}
func (dag *DAG) AddVertex(v *Vertex) {
dag.Vertexes = append(dag.Vertexes, v)
}
func (dag *DAG) AddEdge(from, to *Vertex) {
from.Children = append(from.Children, to)
to.Parents = append(from.Parents, from)
}
func (dag *DAG) BFS(root *Vertex) {
q := queue.New()
visitMap := make(map[string]bool)
visitMap[root.Key] = true
q.Add(root)
for {
if q.Length() == 0 {
fmt.Println("done")
break
}
current := q.Remove().(*Vertex)
fmt.Println("bfs key", current.Key)
for _, v := range current.Children {
fmt.Printf("from:%v to:%s\n", current.Key, v.Key)
if v.Key == root.Key {
panic("back root")
}
if _, ok := visitMap[v.Key]; !ok {
visitMap[v.Key] = true
//fmt.Println("add visit", v.Key)
q.Add(v)
}
}
}
}
func (dag *DAG) DFS(root *Vertex) {
stack := []*Vertex{root}
visitMap := make(map[string]bool)
visitMap[root.Key] = true
for i := 0; i < 10; i++ {
if len(stack) == 0 {
fmt.Println("done")
break
}
if len(stack)-1 < 0 {
panic("unexpected")
}
current := stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Println("dfs key", current.Key)
for _, v := range current.Children {
fmt.Println("from:%v to:%s", current.Key, v.Key)
if v.Key == root.Key {
panic("back root")
}
if _, ok := visitMap[v.Key]; !ok {
visitMap[v.Key] = true
//fmt.Println("add visit", v.Key)
if v.Key == root.Key {
panic("back root")
}
stack = append(stack, v)
}
}
}
}
func main() {
dag := &DAG{}
v1 := &Vertex{Key: "1"}
v2 := &Vertex{Key: "2"}
v3 := &Vertex{Key: "3"}
v4 := &Vertex{Key: "4"}
v5 := &Vertex{Key: "5"}
// 对于有环图,从root点出发,最终会回到root
// non dag
// 5
// >
// /
// 1 <----2
// \ .> \
// > / >
// 3---- >4
dag.AddEdge(v1, v5)
dag.AddEdge(v2, v1)
dag.AddEdge(v1, v3)
dag.AddEdge(v3, v4)
dag.AddEdge(v3, v2)
dag.AddEdge(v2, v4)
dag.AddEdge(v2, v1)
dag.BFS(v1)
//dag.DFS(v1)
}
跟上面例子不一样,顶点2指向顶点1,也就是会有一个1->3->2>1的环
输出
bfs key 1
from:1 to:5
from:1 to:3
bfs key 5
bfs key 3
from:3 to:4
from:3 to:2
bfs key 4
bfs key 2
from:2 to:1
panic: back root
goroutine 1 [running]:
main.(*DAG).BFS(0xc00007cf38, 0xc0000ac000)
/opt/go_work/src/mtest/dag/main.go:50 +0x4e3
main.main()
/opt/go_work/src/mtest/dag/main.go:144 +0x53d
exit status 2
Recommend
-
30
一波三折
-
49
README.md vim2hs ⦂ Vim → Haskell "Vim to Haskell": A collection of vimscripts for Haskell development. Features Written from scratch for clean and org...
-
36
DAG(有向无环图)技术是区块链领域的技术热点之一。DAG技术相比于原来的区块+链的数据结构有更快的交易速度以及更强的可扩展性,但由于其技术门槛和开发难度较高,在DAG技术上深耕的项目并不多见。我们希望能通过对具体项目原理的解析向读...
-
45
-
41
-
16
d3-dag Often data sets are hierarchical, but are not in a tree structure, such as genetic data. In these instances d3-hierarchy may not suit your needs, which is why d3-dag (Directed...
-
26
专题介绍 2009 年,Spark 诞生于加州大学伯克利分校的 AMP 实验室(the Algorithms, Machines and People lab),并于 2010 年开源。2013 年,Spark 捐献给阿帕奇软件基金会(Apache Software Foundation),并于 20...
-
6
golang判断字符串出现的位置及是否包含 次序 · 2018-10-30 07:34:40 · 25919 次点击 · 预计阅读时间 1 分钟 · 大约8小时之前 开始浏览
-
5
Go 实战 | 基于有向无环图的并发执行流的实现 yudotyang · 大约7小时之前 · 12 次点击 · 预计阅...
-
4
有向无环图的拓扑排序 作者:Grey 原文地址: 博客园:有向无环...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK