github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/dag/dag.go (about) 1 // Copyright 2020 The go-simplechain Authors 2 // This file is part of the go-simplechain library. 3 // 4 // The go-simplechain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-simplechain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-simplechain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package dag 18 19 import ( 20 "bytes" 21 "encoding/gob" 22 "fmt" 23 ) 24 25 type Vertex struct { 26 InDegree int 27 OutEdges []int 28 InEdges []int 29 } 30 31 func NewVertex() *Vertex { 32 vertex := &Vertex{ 33 InDegree: 0, 34 OutEdges: make([]int, 0), 35 InEdges: make([]int, 0), 36 } 37 return vertex 38 } 39 40 type Dag struct { 41 V int 42 Consumed int 43 VertexList []*Vertex 44 NextList []int 45 } 46 47 func NewDag(v int) *Dag { 48 dag := &Dag{ 49 V: v, 50 } 51 for i := 0; i < v; i++ { 52 dag.VertexList = append(dag.VertexList, NewVertex()) 53 } 54 return dag 55 } 56 57 func (dag *Dag) AddEdge(from, to int) { 58 dag.VertexList[from].OutEdges = append(dag.VertexList[from].OutEdges, to) 59 dag.VertexList[to].InDegree++ 60 dag.VertexList[to].InEdges = append(dag.VertexList[to].InEdges, from) 61 } 62 63 func (dag *Dag) GetOutEdges(from int) []int { 64 return dag.VertexList[from].OutEdges 65 } 66 67 func (dag *Dag) GetInEdges(to int) []int { 68 return dag.VertexList[to].InEdges 69 } 70 71 func (dag *Dag) HasNext() bool { 72 return dag.Consumed < dag.V 73 } 74 75 func (dag *Dag) Next() []int { 76 if len(dag.NextList) == 0 { 77 for i := 0; i < dag.V; i++ { 78 if dag.VertexList[i].InDegree == 0 { 79 dag.NextList = append(dag.NextList, i) 80 } 81 } 82 } else { 83 //need copy? 84 preList := dag.NextList 85 dag.NextList = []int{} 86 for _, vtxIdx := range preList { 87 for _, outVtxIdx := range dag.VertexList[vtxIdx].OutEdges { 88 dag.VertexList[outVtxIdx].InDegree-- 89 if dag.VertexList[outVtxIdx].InDegree == 0 { 90 dag.NextList = append(dag.NextList, outVtxIdx) 91 } 92 } 93 } 94 } 95 dag.Consumed = dag.Consumed + len(dag.NextList) 96 return dag.NextList 97 } 98 99 func (dag *Dag) InDegree(i int) int { 100 return dag.VertexList[i].InDegree 101 } 102 103 func (dag *Dag) OutDegree(i int) int { 104 return len(dag.VertexList[i].OutEdges) 105 } 106 107 func (dag *Dag) Print() (bytes.Buffer, error) { 108 var buffer bytes.Buffer 109 110 var dagCpy = &Dag{} 111 if err := clone(dag, dagCpy); err != nil { 112 return buffer, err 113 } 114 var level = 0 115 for dagCpy.HasNext() { 116 buffer.WriteString(fmt.Sprintf("level:%d \n ", level)) 117 idxs := dagCpy.Next() 118 for _, idx := range idxs { 119 if level == 0 { 120 buffer.WriteString(fmt.Sprintf("idx:%d ", idx)) 121 } else { 122 buffer.WriteString(fmt.Sprintf("idx:%d%+v ", idx, dagCpy.VertexList[idx].InEdges)) 123 } 124 } 125 buffer.WriteString("\n") 126 level++ 127 } 128 return buffer, nil 129 } 130 131 func clone(src, dest interface{}) error { 132 buff := new(bytes.Buffer) 133 enc := gob.NewEncoder(buff) 134 dec := gob.NewDecoder(buff) 135 if err := enc.Encode(src); err != nil { 136 return err 137 } 138 if err := dec.Decode(dest); err != nil { 139 return err 140 } 141 return nil 142 }