美文网首页
图算法 Graph Dijkstra Prim

图算法 Graph Dijkstra Prim

作者: Sunooo | 来源:发表于2023-03-21 21:13 被阅读0次

Dijkstra's Algorithm(迪杰斯特拉算法)是一种图论算法,由荷兰计算机科学家Edsger W. Dijkstra于1956年提出。它用于解决单源最短路径问题,即在带权重的有向图中,找到从给定源节点到其他所有节点的最短路径。该算法适用于无负权重边的图。

Dijkstra's Algorithm的基本思想是贪心算法,它从源节点开始,每次选择与当前已知最短路径集合相邻的具有最小权重边的节点,并更新这些节点的最短路径长度。这个过程重复进行,直到找到从源节点到所有其他节点的最短路径。

Dijkstra's Algorithm的基本步骤如下:

创建一个集合S,用于存储已确定最短路径的节点。
创建一个距离数组dist,存储从源节点到其他各个节点的最短路径长度。初始化源节点的距离为0,其他节点的距离为无穷大(表示尚未找到路径)。
当集合S中未包含所有节点时:
a. 从尚未处理的节点中选取距离最小的节点u(不在S中)。
b. 将节点u加入集合S。
c. 遍历u的所有邻接节点v。如果通过u到v的路径比当前已知的从源节点到v的路径更短,更新dist[v]。
当算法结束时,距离数组dist包含了从源节点到图中所有其他节点的最短路径长度。如果需要找到实际的路径,可以在算法过程中记录每个节点的前驱节点,并在最后通过回溯前驱节点来找到完整的路径。

Dijkstra's Algorithm在时间复杂度方面较高。使用优先队列来优化查找距离最小的节点时,算法的时间复杂度为O(|V|^2),其中|V|表示图中节点的数量。对于稀疏图,可以通过使用二叉堆、斐波那契堆等高级数据结构将时间复杂度降低到O(|V|log|V| + |E|),其中|E|表示图中边的数量。

struct Graph {
    let vertices: Int
    var adjacencyList: [[(Int, Int)]]

    init(vertices: Int) {
        self.vertices = vertices
        adjacencyList = Array(repeating: [], count: vertices)
    }

    mutating func addEdge(_ source: Int, _ destination: Int, _ weight: Int) {
        adjacencyList[source].append((destination, weight))
    }
}

func dijkstra(graph: Graph, source: Int) -> [Int] {
    var distances = Array(repeating: Int.max, count: graph.vertices)
    distances[source] = 0

    var visited = Array(repeating: false, count: graph.vertices)
    for _ in 0..<graph.vertices {
        var minDistance = Int.max
        var minIndex = -1

        for index in 0..<graph.vertices {
            if !visited[index] && distances[index] < minDistance {
                minDistance = distances[index]
                minIndex = index
            }
        }

        guard minIndex != -1 else { break }

        visited[minIndex] = true
        for (neighbor, weight) in graph.adjacencyList[minIndex] {
            let newDistance = distances[minIndex] + weight
            if newDistance < distances[neighbor] {
                distances[neighbor] = newDistance
            }
        }
    }

    return distances
}
var graph = Graph(vertices: 5)

graph.addEdge(0, 1, 10)
graph.addEdge(0, 2, 5)
graph.addEdge(1, 3, 1)
graph.addEdge(1, 2, 2)
graph.addEdge(2, 1, 3)
graph.addEdge(2, 3, 9)
graph.addEdge(2, 4, 2)
graph.addEdge(3, 4, 4)
graph.addEdge(4, 3, 6)
graph.addEdge(4, 0, 7)

let shortestDistances = dijkstra(graph: graph, source: 0)

print("Shortest distances from source vertex 0: \(shortestDistances)")
// Shortest distances from source vertex 0: [0, 8, 5, 9, 7]

Prim's Algorithm(普里姆算法)是一种用于解决图的最小生成树问题的算法。最小生成树是一个无向连通图的子图,它包括图中所有的顶点和部分边,使得子图形成一棵树,并且边的权重之和最小。Prim's Algorithm由捷克数学家Vojtěch Jarník于1930年提出,美国计算机科学家Robert C. Prim于1957年独立发现了该算法。

Prim's Algorithm基于贪心策略。它从任意一个顶点开始,逐步将顶点添加到生成树中,每次添加的顶点是与已经在树中的顶点相邻并且具有最小权重边的顶点。该过程一直持续到所有顶点都被添加到生成树中。

Prim's Algorithm的基本步骤如下:

初始化一个集合visited,用于存储已经添加到最小生成树中的顶点。
从任意一个顶点开始,将其添加到visited集合中。
当visited集合中的顶点数量小于图中顶点的数量时:
a. 查找具有最小权重的边,使得该边连接已在visited中的顶点和不在visited中的顶点。
b. 将该边以及与其相连的顶点添加到最小生成树中,并将该顶点添加到visited集合中。
当算法结束时,得到的最小生成树包含了图中所有顶点和一部分边,使得生成树的边的权重之和最小。

Prim's Algorithm在时间复杂度方面较高。使用优先队列来优化查找具有最小权重的边时,算法的时间复杂度为O(|V|^2),其中|V|表示图中顶点的数量。对于稀疏图,可以通过使用二叉堆、斐波那契堆等高级数据结构将时间复杂度降低到O(|V|log|V| + |E|),其中|E|表示图中边的数量。

struct Graph {
    let vertices: Int
    var adjacencyList: [[(Int, Int)]]

    init(vertices: Int) {
        self.vertices = vertices
        adjacencyList = Array(repeating: [], count: vertices)
    }

    mutating func addEdge(_ source: Int, _ destination: Int, _ weight: Int) {
        adjacencyList[source].append((destination, weight))
        adjacencyList[destination].append((source, weight))
    }
}

func prim(graph: Graph) -> Int {
    var visited = Array(repeating: false, count: graph.vertices)
    visited[0] = true
    var minCost = 0

    for _ in 1..<graph.vertices {
        var minWeight = Int.max
        var minSource = -1
        var minDestination = -1

        for source in 0..<graph.vertices where visited[source] {
            for (destination, weight) in graph.adjacencyList[source] where !visited[destination] {
                if weight < minWeight {
                    minWeight = weight
                    minSource = source
                    minDestination = destination
                }
            }
        }

        if minSource != -1 && minDestination != -1 {
            visited[minDestination] = true
            minCost += minWeight
        }
    }

    return minCost
}
var graph = Graph(vertices: 5)

graph.addEdge(0, 1, 2)
graph.addEdge(0, 3, 6)
graph.addEdge(1, 2, 3)
graph.addEdge(1, 3, 8)
graph.addEdge(1, 4, 5)
graph.addEdge(2, 4, 7)
graph.addEdge(3, 4, 9)

let minimumCost = prim(graph: graph)

print("Minimum cost of the minimum spanning tree: \(minimumCost)")
// Minimum cost of the minimum spanning tree: 16

github仓库地址 https://github.com/SunZhiC/DataStructuresInSwift

References

Data Structures & Algorithms in Swift by Matthijs Hollemans.
https://github.com/apple/swift-algorithms
https://github.com/raywenderlich/swift-algorithm-club

相关文章

  • JavaScript模拟图操作

    JS操作实现无向网的Prim算法 最后输出结果如下: 其中例子中的图如下: JavaScript实现Dijkstra算法

  • 考研--图论

    1、朴素Dijkstra算法 2、spfa 3、floyd 4、prim最小生成树稠密图, 5、Kruskal最小...

  • 图的结构 BFS DFS

    题目:BFS 一个队列,一个set集合 题目:DFS 题目:Kruskal算法 题目:Prim Dijkstra算法

  • 大数据算法系列13:最小生成树算法

    一. Kruskal算法 二. Prim算法 普里姆(Prim)算法,也是求加权连通图的最小生成树的算法。 基本思...

  • 贪心算法--最小生成树Prim算法

    引言:前两天在复习贪心算法时,看到单源最短路径的Dijkstra算法和最小生成树的Prim算法,由于自己不认真,竟...

  • 最短路算法

    与最小生成树有些不一样.在这里提出三种算法.dijkstra算法,是最普通也是最简单的.与prim算法有些类似,但...

  • 图之最短路径算法--Dijkstra

    Dijkstra算法作者获得过图灵奖,非常著名。该算法能求出给定点到图中所有其它顶点的最短路径。其道理和prim算...

  • Dijkstra算法与Prim算法的异同

    Dijkstra简述 Dijkstra算法用于构建单源点的最短路径树(MST)——即树中某个点到任何其他点的距离都...

  • [Week 2]Princeton Algorithm Part

    回顾 第二周主要内容仍然是关于图的算法,主要内容为: 最小生成树Kruskal算法延时Prim算法即时Prim算法...

  • 图算法(二)最短路

    本文将介绍三种常见的最短路算法:Dijkstra,Floyd,SPFA Dijkstra Dijkstra是有向图...

网友评论

      本文标题:图算法 Graph Dijkstra Prim

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