package main
import (
"fmt"
)
// Index 必须是从0开始依次递增的
var (
NormalNodes = []Node{
Node{
Index : 0,
Depends : []uint32{1,2,3},
},
Node{
Index : 1,
Depends : []uint32{2,3,7},
},
Node{
Index : 2,
Depends : []uint32{3},
},
Node{
Index : 3,
Depends : []uint32{4},
},
Node{
Index : 4,
Depends : []uint32{},
},
Node{
Index : 5,
Depends : []uint32{},
},
Node{
Index : 6,
Depends : []uint32{7},
},
Node{
Index : 7,
Depends : []uint32{5},
},
}
)
var (
ErrorNodes = []Node{
Node{
Index : 0,
Depends : []uint32{1,2,3},
},
Node{
Index : 1,
Depends : []uint32{2,3},
},
Node{
Index : 2,
Depends : []uint32{3},
},
Node{
Index : 3,
Depends : []uint32{4},
},
Node{
Index : 4,
Depends : []uint32{},
},
// 依赖不存在
Node{
Index : 5,
Depends : []uint32{99},
},
}
)
var (
RecursiveNodes = []Node{
Node{
Index : 0,
Depends : []uint32{1,2,3},
},
Node{
Index : 1,
Depends : []uint32{2,3},
},
Node{
Index : 2,
Depends : []uint32{3,5},
},
Node{
Index : 3,
Depends : []uint32{4},
},
Node{
Index : 4,
Depends : []uint32{},
},
// 循环依赖
Node{
Index : 5,
Depends : []uint32{0},
},
}
)
type Node struct {
Index uint32
Depends []uint32
}
func CheckDependExisted(nodes []Node) (error) {
fmt.Printf("CheckDependExisted ...\n")
for _,n := range nodes {
for _,index := range n.Depends {
existed := false
for _,n := range nodes {
if index == n.Index {
existed = true
}
}
if !existed {
return fmt.Errorf("not found dpends for node[%v]", n)
}
}
}
return nil
}
func CheckDependRecursive(nodes []Node) (error) {
fmt.Printf("CheckDependRecursive ...\n")
for _,n := range nodes {
dependsIndex := []uint32{}
err := DeepFirstCheck(n, &dependsIndex, &nodes)
if err != nil {
return err
}
}
return nil
}
func DeepFirstCheck(curnode Node, pathIndexs *[]uint32, globalNodes *[]Node) (error) {
fmt.Printf("DeepFirstCheck,currentIndex[%d],curpath[%v]\n", curnode.Index, *pathIndexs)
// 检查当前节点是否已经在路径里,如果是,则表示有循环依赖
for _,v := range *pathIndexs {
if v == curnode.Index {
newpathIndex := append(*pathIndexs, curnode.Index)
return fmt.Errorf("found recursive dpends [%v]", newpathIndex)
}
}
// 将当前索引保存到路径里
newpathIndex := append(*pathIndexs, curnode.Index)
pathIndexs = &newpathIndex
for _,index := range curnode.Depends {
err := DeepFirstCheck((*globalNodes)[index], pathIndexs, globalNodes)
if err != nil {
return err
}
}
return nil
}
func getPos(n Node, seq []uint32) (uint32,error) {
for i,vIndex := range seq {
if vIndex == n.Index {
return uint32(i), nil
}
}
return 0, fmt.Errorf("failed to get pos for node[%v]", n)
}
// bool : 是否有触发交换
func swapdepends(nodes []Node, indexSeqBefore []uint32) (bool,[]uint32, error) {
fmt.Printf("swapdepends ...\n")
indexSeq := indexSeqBefore
changed := false
for _,vNode := range nodes {
// 如果节点没有依赖,则不处理
if vNode.Depends == nil || len(vNode.Depends) == 0 {
continue
}
// 先找到本节点的在排序中的位置
curPos,err := getPos(vNode, indexSeq)
if err != nil {
return false,nil,err
}
// 找到依赖节点的最大索引值
maxDependsPos := uint32(0)
for _, vIndex := range vNode.Depends {
curPos,err := getPos(nodes[vIndex], indexSeq)
if err != nil {
return false,nil,err
}
if maxDependsPos < curPos {
maxDependsPos = curPos
}
}
// 如果当前节点索引位置 < 最大的依赖索引位置,则进行交换
if curPos < maxDependsPos {
fmt.Printf("ready swap for node [%d %d],", indexSeq[curPos],indexSeq[maxDependsPos])
temp := indexSeq[curPos]
indexSeq[curPos] = indexSeq[maxDependsPos]
indexSeq[maxDependsPos] = temp
fmt.Printf("after swap seq [%v]\n", indexSeq)
changed = true
}
}
return changed,indexSeq,nil
}
func SortNode (nodes []Node) ([]uint32, error) {
fmt.Printf("SortNode ...\n")
indexSeq := []uint32{}
for _,v := range nodes {
indexSeq = append(indexSeq, v.Index)
}
fmt.Printf("init seq [%v]\n", indexSeq)
changed,newseq,err := swapdepends(nodes, indexSeq)
for maxSwapCounter := 100;maxSwapCounter>0;maxSwapCounter-- {
if err != nil {
return nil, err
}
if !changed {
return newseq,nil
}
changed,newseq,err = swapdepends(nodes, newseq)
}
return nil, fmt.Errorf("failed to sort for[%v]", nodes)
}
func CheckAndSort (nodes []Node) ([]uint32, error) {
err := CheckDependExisted(nodes)
if err != nil {
fmt.Printf("failed to check depends for [%v]\n", err)
return nil, err
}
err = CheckDependRecursive(nodes)
if err != nil {
fmt.Printf("failed to check depends for [%v]\n", err)
return nil, err
}
sortedseq,err := SortNode(nodes)
if err != nil {
fmt.Printf("failed to sort for [%v]\n", err)
return nil, err
}
fmt.Printf("sorted seq [%v]\n", sortedseq)
return sortedseq, nil
}
func main () {
fmt.Printf("main ...\n")
fmt.Printf("\n------------------check for normal nodes----------------------\n\n")
CheckAndSort(NormalNodes)
fmt.Printf("\n------------------check for not existed nodes----------------------\n\n")
CheckAndSort(ErrorNodes)
fmt.Printf("\n------------------check for recursive nodes----------------------\n\n")
CheckAndSort(RecursiveNodes)
}