美文网首页
17-Prim算法

17-Prim算法

作者: ducktobey | 来源:发表于2019-12-19 19:03 被阅读0次

在研究Prim算法之前,首先要了解一个概念。切分定理

切分定理

切分(Cut):把图中的节点分为两部分,成为一个切分

例如下图,该图上有5个顶点

现在,利用虚线,将图分割为2部分,第一部分有3个节点,第二部分有2个节点,这就叫做一个切分

所以切分可以通过这种式子来进行表示C = (S,T),其中S = {A,B,D},T = {C,E}

横切边(Crossing Edge):如果一个边的两个顶点,分别属于切分的两部分,这个边就称为横切边

所以上图中的边BC,BE,DE就是横切边,因为这些边,一部分在左边的子图中,一部分在右边的子图中。

切分定理:给定任意切分,横切边中权值最小的边必然属于最小生成树

意思就是说,如上图的3条横切边,权值最小的一条,必然属于最小生成树的边

Prim算法执行过程

假设G = (V,E)是有权的连通图(无向),A是G中最小生成树的边集

  1. G表示图,V表示顶点,E表示边
  2. 组成最小生成树的边都会放到集合A中
  3. A最开始的时候,是一个空集合

再定义一个集合S,用来存放切分的起点和切完后被切出来的顶点,所以集合S中的顶点都是属于V的,然后重复找到切分的最小横切边,然后将找到的边存放到结合A中,同时将找到的顶点放入集合S中。直到S = V为止,就说明找到了最小生成树的所有边和顶点。

以上执行过程比较抽象,如果将上面流程转换为流程图,则可以通过下面的流程来进行表示

假设现在有如下的图,现在从顶点A开始进行切分,所以首先将A加入到集合S中

在对顶点A进行切分,所以以顶点A的outEdges进行切分,利用虚线表示如下

通过这样切分以后,就会产生2条横切边,分别为4和8,结合前面的切分定理,最终会选择AB这条边最为最小生成树的边,现在找出了一条最小生成树的边,所以将AB这条边加入到集合A中,并且将横切边的另外一顶点B加入到集合S中,现在集合S中就存放了2个顶点{A,B},最终切分后的结果如下

现在相当于将图切为了两个部分,一部分的顶点存放在集合S中,另外一部分继续存放在原来的内存中。所以以集合S中的顶点与原来图中的顶点,将两个部分中有边存在的部分作为一个切边,所以最终的切分如下

切边找到后,又根据切分定理,找出去权值最小的一条边,然后将边放入到集合A中,将横切边的另外一顶点放入集合S中,由于现在有两条边权值相同,所以任意选择一条均可。在本示例中选择BC条边,所以现在将新找到的一条边加BC入到A中,并且将C加入到S中,现在S中就存放了3个顶点{A,B,C},切分后的结果如下

再利用前面寻找切分的方法,可以找到如下图所示的切分

根据现在的切分,找出 权值最小的边CI,将边CI加入到集合A中,另外一顶点I加入到S中,所以最终切分后的结果如下

再利用前面寻找切分的方法,可以找到下一个如下图所示的切分

这样一切,又可以找到权值最小的横切边CF,所以将边CF加入到结合A中,将顶点F加入到集合S中,最终切分后的结果如下

继续寻找新的切分,所以,很容易就知道新的切分如下所示

然后又从横切边中找出权值最小的边,所以本次权值最小的边为GF,所以将GF这条边加入到集合A中,顶点G加入到S中,最终切分后的结果如下

继续进行切分,找出一条最小生成树的边,所以本次的切分如下。不过需要注意,这里有一个小细节,IG这条边没有被最为一条横切边,原因是如果将这条边作为横切边以后,万一被选中,那么原来的最小生成树就会成环,这就不符合最小生成树的要求,所以在选择很切边时,可能有一些小细节需要注意

根据上面的切分,最终又会选择出一条权值最小的边HG,将这表边加入到集合A中,同时将H加入到集合S中,所以最终切分后的结果如下

继续进行切分,本次的切分如下所示

找出权值最小的边CD,将边CD加入到集合A中,将新的顶点D加入到S中,所以本次切分后的结果如下

继续进行切分,本次气氛如下图所示

找出权值最小的边DE,将DE加入到结合A中,将新的顶点E加入到集合S中,所以本次切分的结果如下

到现在可以发现,原来图中的所以顶点,都已经加入到了集合S中,所以即表示最小生成树已经完成。所以去掉多于的线以后,最终的最小生成树如下

所以经过这样一个流程下来,相信已经可以理解前面最新过程部分的概括了。

结合前面的分析,得到代码如下

private Set<EdgeInfo<V, E>> prim() {
    Iterator<Vertex<V,E>> it = vertices.values().iterator();
    if (!it.hasNext()) return null;
    Set<EdgeInfo<V, E>> edgeInfos = new HashSet<>();
    Set<Vertex<V,E>> addedVertices = new HashSet<>();
    Vertex<V,E> vertex = it.next();
    addedVertices.add(vertex);
    MinHeap<Edge<V,E>> heap = new MinHeap<>(vertex.outEdges,edgeComparator);
    int edgeSize = vertices.size() - 1;
    while (!heap.isEmpty() && edgeInfos.size() < edgeSize) {
        Edge<V,E> edge = heap.remove();
        if (addedVertices.contains(edge.to)) continue;
        edgeInfos.add(edge.info());
        addedVertices.add(edge.to);
        heap.addAll(edge.to.outEdges);
    }
    return edgeInfos;
}

demo下载地址

完!

相关文章

  • 17-Prim算法

    在研究Prim算法之前,首先要了解一个概念。切分定理 切分定理 切分(Cut):把图中的节点分为两部分,成为一个切...

  • 匈牙利算法

    算法思想 算法流程 算法步骤 算法实现 python 算法应用

  • web开发需要知道的几个算法

    算法分类 快速排序算法 深度优先算法 广度优先算法 堆排序算法 归并排序算法

  • 机器学习算法

    机器学习的算法分监督算法和无监督 算法。监督算法包括回归算法,神经网络,SVM;无监督算法包括聚类算法,降维算法。...

  • 字符串匹配

    BF 算法和 RK 算法BM 算法和 KMP 算法

  • 垃圾回收算法有几种类型? 他们对应的优缺点又是什么?

    常见的垃圾回收算法有: 标记-清除算法、复制算法、标记-整理算法、分代收集算法 标记-清除算法 标记—清除算法包括...

  • 头条-手撕代码

    [toc] 图算法 以及最短路径算法 树算法 手写LRU 排序算法 链表算法

  • 关于一些算法

    我们平常说的算法按照使用方向加密算法,排序算法,搜索算法,优化算法,音视频处理算法,图片处理算法 1.加密解密算法...

  • 给我巨大影响的技术书籍

    算法《算法概论》《算法设计与分析基础》 Anany Levitin《算法引论》Udi Manber《算法导论》《什...

  • 缓存相关

    cache淘汰算法:LIRS 算法 缓存那些事 Redis缓存淘汰算法,LRU算法,LRU算法讲解

网友评论

      本文标题:17-Prim算法

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