作者: 原来哥哥是万家灯火 | 来源:发表于2022-10-09 14:55 被阅读0次

    几个概念:有向图、无向图、加权图、简单图、联通、联通分量、生成树、强连通分量、强联通图
    图的存储:邻接矩阵(二维、一维)、邻接表
    图的遍历:深搜、广搜
    (无向加权图)最小生成树:kruskal算法过程及证明、prime算法过程
    单源最短距离问题:dijkstra算法
    深搜和回溯的区别:个人理解是深搜是图的一种遍历方式(树也属于图),回溯是只用于树

    package main
    
    import (
        "fmt"
        "math"
        "sort"
        "strconv"
    )
    
    func main() {
        vertexes := []string{"A", "B", "C", "D", "E", "F"}
        edges := []string{
            "AB,4", "AC,8", "AD,45", "AF,3",
            "BA,4", "BC,14", "BE,20", "BF,5",
            "CA,8", "CB,14", "CD,28", "CE,9",
            "DA,45", "DC,28", "DE,10",
            "EB,20", "EC,9", "EF,13", "ED,10",
            "FA,3", "FB,5", "FE,13",
        }
        g := NewGraph(vertexes, edges)
    
        g.DFS()
        g.BFS(0)
        g.Kruskal()
        g.Prime(0)
        g.Dijkstra(0)
    }
    
    type Vertex struct {
        Name      string
        FirstEdge *Edge
    }
    
    type Edge struct {
        V        int
        W        int
        Cost     int
        NextEdge *Edge
    }
    
    type Graph struct {
        VertexNum    int
        EdgeNum      int
        AdjacentList []Vertex
    }
    
    func NewGraph(vertexes []string, edges []string) Graph {
        g := Graph{}
        g.VertexNum = len(vertexes)
        g.EdgeNum = len(edges) / 2 // 无向图
        g.AdjacentList = make([]Vertex, len(vertexes))
    
        m := map[string]int{}
        for i, vertex := range vertexes {
            v := Vertex{
                Name: vertex,
            }
            g.AdjacentList[i] = v
            m[vertex] = i
        }
    
        for _, edgeStr := range edges {
            v := m[string(edgeStr[0])]
            w := m[string(edgeStr[1])]
            cost, _ := strconv.Atoi(edgeStr[3:])
            edge := Edge{
                V:        v,
                W:        w,
                Cost:     cost,
                NextEdge: g.AdjacentList[v].FirstEdge,
            }
            g.AdjacentList[v].FirstEdge = &edge
        }
    
        return g
    }
    
    func (g *Graph) DFS() {
        visited := map[int]bool{}
        for i, _ := range g.AdjacentList {
            g.dfs(i, visited)
        }
    }
    
    func (g *Graph) dfs(v int, visited map[int]bool) {
        if visited[v] {
            return
        }
        vertex := g.AdjacentList[v]
        visited[v] = true
        fmt.Println("先深遍历", vertex.Name)
    
        edge := vertex.FirstEdge
        for edge != nil {
            if visited[edge.W] {
                edge = edge.NextEdge
                continue
            }
            g.dfs(edge.W, visited)
        }
    }
    
    func (g *Graph) BFS(start int) {
        visited := map[int]bool{}
    
        var queue = []int{
            start,
        }
    
        i := 0
        for ; i < len(queue); i++ {
            k := queue[i]
            vertex := g.AdjacentList[k]
            if visited[k] {
                continue
            }
            fmt.Println("先广遍历", vertex.Name)
            visited[k] = true
    
            edge := vertex.FirstEdge
            for edge != nil {
                if !visited[edge.W] {
                    queue = append(queue, edge.W)
                }
                edge = edge.NextEdge
            }
        }
    }
    
    func (g *Graph) Kruskal() (mst []Edge) {
        sortedEdges := g.sortEdges()
        mst = make([]Edge, g.VertexNum-1)
    
        i := 0
        l := 0
        selectedVertexes := map[int]bool{}
    
        for l < g.VertexNum-1 {
            edge := sortedEdges[i]
            if !(selectedVertexes[edge.V] && selectedVertexes[edge.W]) {
                selectedVertexes[edge.V] = true
                selectedVertexes[edge.W] = true
                mst[l] = edge
                l++
            }
            i++
        }
    
        fmt.Println("Kruskal结果")
        for _, edge := range mst {
            fmt.Println(g.AdjacentList[edge.V].Name+g.AdjacentList[edge.W].Name, edge.Cost)
        }
    
        return
    }
    
    func (g *Graph) sortEdges() []Edge {
        visited := map[int]bool{}
    
        edges := make([]Edge, g.EdgeNum)
        l := 0
        for i, vertex := range g.AdjacentList {
            edge := vertex.FirstEdge
            for edge != nil {
                if !visited[edge.W] {
                    edges[l] = *edge
                    l++
                }
                edge = edge.NextEdge
            }
            visited[i] = true
        }
    
        sort.Slice(edges, func(i, j int) bool {
            return edges[i].Cost < edges[j].Cost
        })
    
        return edges
    }
    
    func (g *Graph) Prime(start int) (mst []Edge) {
        fmt.Println("prime计算过程")
        selectedVertex := map[int]bool{start: true}
        unSelectedVertex := map[int]Edge{}
    
        lastSelectVertex := start
        for len(mst) < g.VertexNum-1 {
            var minCost = math.MaxInt64
            var minEdge Edge
    
            for i, _ := range g.AdjacentList {
                if selectedVertex[i] {
                    continue
                }
                newCost, _ := g.getCost(lastSelectVertex, i)
                if edge, initialized := unSelectedVertex[i]; !initialized || newCost < edge.Cost {
                    unSelectedVertex[i] = Edge{
                        V:    lastSelectVertex,
                        W:    i,
                        Cost: newCost,
                    }
                }
    
                if unSelectedVertex[i].Cost < minCost {
                    minCost = unSelectedVertex[i].Cost
                    minEdge = unSelectedVertex[i]
                }
            }
    
            fmt.Println()
            for i, edge := range unSelectedVertex {
                if selectedVertex[edge.W] {
                    continue
                }
                fmt.Println(i, g.AdjacentList[edge.V].Name+g.AdjacentList[edge.W].Name, edge.Cost)
            }
            fmt.Println("选择最小边: ", 
    g.AdjacentList[minEdge.V].Name+g.AdjacentList[minEdge.W].Name, minEdge.Cost)
    
            mst = append(mst, minEdge)
            lastSelectVertex = minEdge.W
            selectedVertex[minEdge.W] = true
        }
    
        fmt.Println("最终结果")
        for i, edge := range mst {
            fmt.Println(i, g.AdjacentList[edge.V].Name+g.AdjacentList[edge.W].Name, edge.Cost)
        }
    
        return
    }
    
    func (g *Graph) getVertex(i int) Vertex {
        return g.AdjacentList[i]
    }
    
    func (g *Graph) getCost(from int, to int) (cost int, isInfinity bool) {
        startVertex := g.AdjacentList[from]
        edge := startVertex.FirstEdge
        for edge != nil {
            if edge.W == to {
                return edge.Cost, false
            }
            edge = edge.NextEdge
        }
        return math.MaxInt64, true
    }
    
    func (g *Graph) Dijkstra(start int) {
        fmt.Println("dijkstra计算过程")
        type vertexRecord struct {
            path     string
            cost     int
            selected bool
        }
    
        vertexes := make([]vertexRecord, g.VertexNum)
    
        for i, _ := range g.AdjacentList {
            if i == start {
                vertexes[start] = vertexRecord{
                    path:     g.getVertex(start).Name,
                    cost:     0,
                    selected: true,
                }
                continue
            }
            cost, _ := g.getCost(start, i)
            vertexes[i] = vertexRecord{
                path: g.getVertex(start).Name + g.getVertex(i).Name,
                cost: cost,
            }
        }
    
        lastSelect := start
        for i := 0; i < g.VertexNum-1; i++ {
            minCost := math.MaxInt64
            minCostVertex := 0
            for j, _ := range vertexes {
                if vertexes[j].selected {
                    continue
                }
                lastSelectVertex := vertexes[lastSelect]
    
                cost, isInfinity := g.getCost(lastSelect, j)
                if !isInfinity && lastSelectVertex.cost+cost < vertexes[j].cost {
                    vertexes[j].cost = lastSelectVertex.cost + cost
                    vertexes[j].path = lastSelectVertex.path + g.getVertex(j).Name
                }
    
                fmt.Println(fmt.Sprintf(`A到%s最近的路径是%s,其耗费是%d`,
     g.getVertex(j).Name, vertexes[j].path, vertexes[j].cost))
                if vertexes[j].cost < minCost {
                    minCost = vertexes[j].cost
                    minCostVertex = j
                }
            }
            fmt.Println()
            fmt.Println("本次最短路径为", vertexes[minCostVertex].path, vertexes[minCostVertex].cost)
            fmt.Println()
    
            vertexes[minCostVertex].selected = true
            lastSelect = minCostVertex
        }
    
        for i, vertex := range vertexes {
            fmt.Println(i, vertex.path, vertex.cost)
        }
    }
    

    相关文章

      网友评论

          本文标题:

          本文链接:https://www.haomeiwen.com/subject/wdmmartx.html