图 最短路径Floyd 算法#go语言
package sufa import ( "fmt" mapset "github.com/deckarep/golang-set" "math/rand" "src/goProject1/utils" "strconv" ) type GNode struct { Name string NodeList []*GNode EdgeList [][]*Edge Direct [][]int } type Edge struct { ParentNode *GNode NextNode *GNode RelationShip string Weight int } var ( gNodes []*GNode edges []*Edge ) func init() { gNodes = make([]*GNode, 0) edges = make([]*Edge, 0) } func Main() { var i = 0 _ = utils.ReadLine("./sufa/te.csv", func(line []byte) { s := string(line) s = utils.CompressStr(s) s1 := utils.SplitString(s, ",") //fmt.Println(s) //fmt.Println(len(s1), s1) if len(s1) == 4 && i < 10000 { //fmt.Print(s,s1, "\n") weight, err := strconv.Atoi(s1[2]) if err != nil { //return weight = 1 } addOne(s1[0], s1[3], s1[1], weight) fmt.Print(i, "\r") } i++ }) fmt.Print("\n-") //for i2, node := range gNodes { // fmt.Println(i2, node.Name, *node.NodeList[0], node.EdgeList[0], node.Direct[0]) //} res, path := GetMin("mao1", "mao1000") //fmt.Println(gNodes) fmt.Print("\n") fmt.Println(res, path) //for i2, edge := range edges { // fmt.Println(i2, edge.ParentNode.Name, edge.NextNode.Name, edge.RelationShip,edge.Weight) //} } func addOne(p, n, relationShip string, weight int) { var ( pNode *GNode nNode *GNode edge *Edge ) pNode = GetNode(p) nNode = GetNode(n) if pNode.Name == "" { pNode = new(GNode) pNode.Name = p gNodes = append(gNodes, pNode) } if nNode.Name == "" { nNode = new(GNode) nNode.Name = n gNodes = append(gNodes, nNode) } edge = GetEdge(p, n, relationShip, weight) if edge.ParentNode != nil || edge.NextNode != nil { //addRelation(pNode, nNode, edge) return } edge = &Edge{ ParentNode: pNode, NextNode: nNode, RelationShip: relationShip, Weight: weight, } edges = append(edges, edge) //fmt.Println(p,n) addRelation(pNode, nNode, edge) } func addRelation(pNode, nNode *GNode, edge *Edge) { var pFlag = 0 var nFlag = 0 var i1 = 0 var i2 = 0 for ; i1 < len(pNode.NodeList); i1++ { if pNode.NodeList[i1].Name == nNode.Name { pFlag = len(pNode.EdgeList[i1]) break } } for ; i2 < len(nNode.NodeList); i2++ { if nNode.NodeList[i2].Name == pNode.Name { nFlag = len(nNode.EdgeList[i2]) break } } if pFlag > 0 { pNode.EdgeList[i1] = append(pNode.EdgeList[i1], edge) pNode.Direct[i1] = append(pNode.Direct[i1], edge.Weight) } if pFlag <= 0 || i1 == 0 { pNode.NodeList = append(pNode.NodeList, nNode) pNode.EdgeList = append(pNode.EdgeList, []*Edge{edge}) pNode.Direct = append(pNode.Direct, []int{edge.Weight}) } if nFlag > 0 { nNode.EdgeList[i2] = append(nNode.EdgeList[i2], &Edge{ ParentNode: edge.ParentNode, NextNode: edge.NextNode, RelationShip: edge.RelationShip, Weight: -edge.Weight, }) nNode.Direct[i2] = append(nNode.Direct[i2], -edge.Weight) } if nFlag <= 0 || i2 == 0 { nNode.NodeList = append(nNode.NodeList, pNode) nNode.EdgeList = append(nNode.EdgeList, []*Edge{&Edge{ ParentNode: edge.ParentNode, NextNode: edge.NextNode, RelationShip: edge.RelationShip, Weight: -edge.Weight, }}) nNode.Direct = append(nNode.Direct, []int{-edge.Weight}) } //fmt.Println(pFlag, nFlag,i1,i2, pNode.Name, nNode.Name, pNode.NodeList, nNode.NodeList, pNode.EdgeList, nNode.EdgeList) } func GetEdge(p, n, relationShip string, weight int) *Edge { for i := 0; i < len(edges); i++ { if p != "" && n != "" && relationShip != "" { if edges[i].ParentNode.Name == p && edges[i].NextNode.Name == n && //edges[i].RelationShip == relationShip && edges[i].Weight == weight { return edges[i] } } } return &Edge{} } func GetNode(name string) *GNode { for i := 0; i < len(gNodes); i++ { if gNodes[i].Name == name { return gNodes[i] } } return &GNode{ Name: "", } } func GetMin(pName, nName string) (li int, path []interface{}) { pNode := GetNode(pName) nNode := GetNode(nName) fmt.Println(pNode.Name, nNode.Name) if pNode.Name == "" || nNode.Name == "" || pName == nName || pNode == nil || nNode == nil { return } var list1 = make(map[interface{}]interface{}, 0) var parentNodeMap = make(map[interface{}]interface{}, 0) s := mapset.NewSet() list1[pNode] = 0 type fType func(node *GNode) var f fType f = func(node *GNode) { if len(s.ToSlice()) == len(gNodes) || node == nil { return } //s.Add(node) var minL = -1 //var minNode *GNode for i := 0; i < len(node.NodeList); i++ { nextNode := node.NodeList[i] edge := node.EdgeList[i] direct := node.Direct[i] var minLength = -1 for j := 0; j < len(edge); j++ { //edge1:=edge[j] direct1 := direct[j] if direct1 <= 0 { continue } if minLength == -1 { minLength = direct1 } if direct1 < minLength { minLength = direct1 } } if minLength <= 0 { continue } if minL == -1 { minL = minLength //minNode = nextNode } if minLength < minL { minL = minLength //minNode = nextNode } if nextNode != nil && minLength > 0 { s1, ok1 := list1[node] s2, ok2 := list1[nextNode] if (!ok2 && ok1) || (ok1 && ok2 && s1.(int)+minLength <= s2.(int)) { list1[nextNode] = list1[node].(int) + minLength parentNodeMap[nextNode] = node s.Add(node) f(nextNode) } //s3, ok3 := parentNodeMap[node] //s4, ok4 := parentNodeMap[nextNode] //if s.Contains(node) && s.Contains(nextNode) && ok3 && ok4 && // s3 == nextNode && s4 == node{ // fmt.Println("=== == ") // continue //} } } //if minNode != nil && minL >0{ // s1, ok1 := list1[node] // s2, ok2 := list1[minNode] // if (!ok2 && ok1) || (ok1 && ok2 && s1.(int)+minL <= s2.(int)) { // list1[minNode] = list1[node].(int) + minL // } // parentNodeMap[node.Name+minNode.Name] = minL // s.Add(node) // f(minNode) //} } f(pNode) if list1[nNode] != nil { li = list1[nNode].(int) } //fmt.Println(list1) //fmt.Println(nNode) //for i, i2 := range list1 { // if parentNodeMap[i.(*GNode)] != nil{ // fmt.Println(i.(*GNode).Name, i2,parentNodeMap[i.(*GNode)].(*GNode).Name) // }else { // fmt.Println(i.(*GNode).Name, i2,parentNodeMap[i.(*GNode)]) // } // //res = append(res, parentNodeMap[i.(*GNode)]) // //} var ff fType ff = func(node *GNode) { if parentNodeMap[node] == nil { return } pgNode := parentNodeMap[node].(*GNode) path = append(path, pgNode) ff(pgNode) } path = append(path, nNode) ff(nNode) for i := 0; i < len(path)/2; i++ { var inner interface{} inner = path[i] path[i] = path[len(path)-1-i] path[len(path)-1-i] = inner } for i := 0; i < len(path); i++ { fmt.Println(path[i].(*GNode).Name) } //fmt.Println(res) //fmt.Println(parentNodeMap) return }
utils.go
package utils import ( "bufio" "io" "os" "fmt" mapset "github.com/deckarep/golang-set" " regexp" ) func ReadLine(filePth string, hookfn func([]byte)) error { f, err := os.Open(filePth) if err != nil { return err } defer f.Close() bfRd := bufio.NewReader(f) for { line, err := bfRd.ReadBytes('\n') hookfn(line) //放在错误处理前面,即使发生错误,也会处理已经读取到的数据。 if err != nil { //遇到任何错误立即返回,并忽略 EOF 错误信息 if err == io.EOF { return nil } return err } } //return nil } func SplitString1(str string, part string) []string { set1 := SplitStringT(str, part) set2 := SplitStringB(str, part) set3 := set1.Union(set2) //fmt.Println(set1, set2) s2 := make([]string, len(set3.ToSlice())) for i, v := range set3.ToSlice() { s2[i] = v.(string) //fmt.Println(i,v) } // //for i := len(s1)-1; i >= 0; i-- { // for j := len(s2)-1; j >= 0; j-- { // if s1[i] == s2[j] { // s1 = append(s1[:i],s1[i+1: ]...) // } // } //} //s2 = append(s2, s1...) //fmt.Printf("%v", s2) return s2 } func SplitString(str string, part string) []string { //str = str[-1:0] part = partner(part) var l = len(part) var res []string var ( start int = 0 end int = 0 i = 0 ) end = len(str) start = end for i = len(str) - 1; i >= 0; i-- { if i-l < 0 { break } if str[i-l:i] == part { start = i res = append(res, str[start:end]) end = start - l break } } for i = i - 1; i >= 0; i-- { if i-l <= 0 { start = 0 res = append(res, str[start:end]) break } //fmt.Println(start, end) if str[i-l:i] == part { start = i //fmt.Println(start, end) res = append(res, str[start:end]) } end = start - l } for i := 0; i < len(res)/2; i++ { var st string st = res[i] res[i] = res[len(res)-i-1] res[len(res)-i-1] = st } return res } func SplitStringB(str string, part string) mapset.Set { part = CompressStr(part) reg := regexp.MustCompile(part + `*[\W\w ]+` + part + ``) if reg == nil { fmt.Println("MustCompile err") return nil } s := reg.FindAllString(str, -1) //if part == "\\\\"{ // part = part[1:] //} fmt.Println(part, s, str) part = partner(part) var s2 = mapset.NewSet() for _, i2 := range s { if string(i2[0]) == part { i2 = string(i2[1:]) } if string(i2[len(i2)-1]) == part { i2 = i2[:len(i2)-1] } s2.Add(i2) //fmt.Println(i2) } return s2 } func SplitStringT(str string, part string) mapset.Set { part = CompressStr(part) reg := regexp.MustCompile(part + `[\W\w ]+` + part + `*`) if reg == nil { fmt.Println("MustCompile err") return nil } s := reg.FindAllString(str, -1) var s2 = mapset.NewSet() fmt.Println(part, s, str) part = partner(part) for _, i2 := range s { if string(i2[0]) == part { i2 = string(i2[1:]) } if string(i2[len(i2)-1]) == part { i2 = i2[:len(i2)-1] } s2.Add(i2) //fmt.Println(i2) } //fmt.Printf("%v", s2) return s2 } func se() { kide := mapset.NewSet() kide.Add("xiaorui.cc") kide.Add("blog.xiaorui.cc") kide.Add("vps.xiaorui.cc") kide.Add("linode.xiaorui.cc") special := []interface{}{"Biology", "Chemistry"} scienceClasses := mapset.NewSetFromSlice(special) address := mapset.NewSet() address.Add("beijing") address.Add("nanjing") address.Add("shanghai") bonusClasses := mapset.NewSet() bonusClasses.Add("Go Programming") bonusClasses.Add("Python Programming") //一个并集的运算 allClasses := kide.Union(scienceClasses).Union(address).Union(bonusClasses) fmt.Println(allClasses) //是否包含"Cookiing" fmt.Println(scienceClasses.Contains("Cooking")) //false //两个集合的差集 fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding} //两个集合的交集 fmt.Println(scienceClasses.Intersect(kide)) //Set{Biology} //有多少基数 fmt.Println(bonusClasses.Cardinality()) //2 } func partner(part string) string { for i := len(part) - 1; i >= 0; i-- { if len(part) < 2 || i < 2 { break } var ca bool ca = string(part[i-1]) == "\\" || string(part[i]) == "?" || string(part[i]) == "+" || string(part[i]) == "-" || string(part[i]) == "*" if ca { part = part[:i-1] + part[i:] i = i - 1 } } return part }