图的最小生成树(Prim、Kruskal)

理论:

Prim:

基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:

在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。

此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。

Prim算法的核心:始终保持TE中的边集构成一棵生成树。

Kruskal:

假设连通网N=(V,{E})。则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。

在E中选择最小代价的边,若该边依附的顶点落在T中不同的连通分量中,则将该边加入到T中,否则舍去此边而选择下一条代价最小的边,依次类推,直到T中所有顶点都在同一连通分量上为止。

两者比较;

prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。

java实现

Vertex.java

package 图;

public class Vertex{
    String value;
    boolean isVisited;
    Vertex(String value)
    {
        this.value=value;
        this.isVisited=false;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public boolean isVisited() {
        return isVisited;
    }
    public void setVisited(boolean isVisited) {
        this.isVisited = isVisited;
    }

}

Edge.java

package 图;

public class Edge{
    Vertex start;
    Vertex end;
    int value;
    public Vertex getStart() {
        return start;
    }

    public void setStart(Vertex start) {
        this.start = start;
    }

    public Vertex getEnd() {
        return end;
    }

    public void setEnd(Vertex end) {
        this.end = end;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    Edge(Vertex start,Vertex end, int value){
        this.start=start;
        this.end=end;
        this.value=value;
    }
}

Graph.java

    package 图;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Stack;

    public class Graph {

        public static List<Vertex> vertexList=new ArrayList<Vertex>();
        public static List<Edge> EdgeQueue=new ArrayList<Edge>();
        public static List<Vertex> newVertex=new ArrayList<Vertex>();
        public static List<Edge> newEdge=new ArrayList<Edge>();

        public static void buildGraph(){
            Vertex a=new Vertex("a");
            vertexList.add(a);
            Vertex b=new Vertex("b");
            vertexList.add(b);
            Vertex c=new Vertex("c");
            vertexList.add(c);
            Vertex d=new Vertex("d");
            vertexList.add(d);
            Vertex e=new Vertex("e");
            vertexList.add(e);
            Vertex f=new Vertex("f");
            vertexList.add(f);

            addEdge(a, b, 3);
            addEdge(a, e, 6);
            addEdge(a, f, 5);
            addEdge(b, a, 3);
            addEdge(b, c, 1);
            addEdge(b, f, 4);
            addEdge(c, b, 1);
            addEdge(c, d, 6);
            addEdge(c, f, 4);
            addEdge(d, c, 6);
            addEdge(d, f, 5);
            addEdge(d, e, 8);
            addEdge(e, d, 8);
            addEdge(e, f, 2);
            addEdge(e, a, 6);
            addEdge(f, a, 5);
            addEdge(f, b, 4);
            addEdge(f, c, 4);
            addEdge(f, d, 5);
            addEdge(f, e, 2);

        }

        public static void addEdge(Vertex start,Vertex end,int value){
            Edge e=new Edge(start,end,value);
            EdgeQueue.add(e);
        }
        public static boolean containVertex(Vertex v){

            for(Vertex each:newVertex)
            {
                if(each.value.equals(v.value))
                    return true;
            }
            return false;
        }

        public static void prim(){
            buildGraph();
            Vertex start=vertexList.get(0);
            newVertex.add(start);

            for(int i=0; i<vertexList.size(); i++)
            {
                Vertex temp=new Vertex(start.value);
                Edge tempEdge=new Edge(start, start, 1000);

                for(Vertex v:newVertex)
                {
                    for(Edge e:EdgeQueue)
                    {
                        if(e.start==v && !containVertex(e.end))
                        {
                            if(tempEdge.value>e.value)
                            {
                                tempEdge=e;
                                temp=e.end;
                            }
                        }
                    }
                }
                newVertex.add(temp);
            }

            Iterator<Vertex>i=newVertex.iterator();
            while(i.hasNext())
            {
                Vertex v=i.next();
                System.out.print(v.value+" ");
            }
        }

        public static void kruskal(){
            buildGraph();
            sort();
        }

        public static void sort(){
            Comparator<Edge>comparator=new Comparator<Edge>(){

                @Override
                public int compare(Edge e1, Edge e2) {
                    // TODO Auto-generated method stub
                    return e1.getValue()-e2.getValue();
                }
            };
            Collections.sort(EdgeQueue,comparator);
        }

        public static void main(String[] args) {
               prim();
        }
    }
    
时间: 2024-08-06 09:29:21

图的最小生成树(Prim、Kruskal)的相关文章

poj1861 最小生成树 prim &amp; kruskal

// poj1861 最小生成树 prim & kruskal // // 一个水题,为的只是回味一下模板,日后好有个照应不是 #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <iostream> using namespace std; const int MAX_N = 1008; const int INF =

图的最小生成树:Kruskal算法实现

图的最小生成树,就是基于图,假设其有n的顶点,那么就要构建一颗连通树,使其各边权重和最小.最小生成树的实现算法主要有两种:Prim算法和Kruskal算法.Prim算法在前面已经介绍过,本文着重介绍Kruskal算法及其实现,其中图的实现以及相关操作,采用前面博文C++ 图的实现中的实现方式,由于本文重点在于Kruskal算法的实现,所有就不在图的构建以及相关操作中过多赘述. 对于Kruskal算法,维基的解释其实已经很详细了,算法思想很好理解,不多说明,直接看实现. /* *无向图查找最小树:

邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)

matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <limits.h> #include "aqueue.h" #define MAX_VALUE INT_MAX #define MAX_NUM 100 typedef char node_type; typedef struct matrix { node_type vertex[M

图的最小生成树prim算法模板

用prim算法构建最小生成树适合顶点数据较少而边较多的图 prim算法生成连通图的最小生成胡模板伪代码: G为图,一般为全局变量,数组d为顶点与集合s的最短距离 Prim(G, d[]){ 初始化; for (循环n次){ u = 使d[u]最小的还未访问的顶点的标号; 记u 已被访问; for(从u出发到达的所有顶点v){ if (v未被访问&&以u为中介点使得v与集合S的嘴短距离d[v]更优){ 将G[u][v]赋值给v与结合S的最短距离d[v]; } } } } 邻接矩阵版: 1 /

图的最小生成树——Prim算法

Prim算法 Prim算法求最小生成树是采取蓝白点的思想,白点代表已经加入最小生成树的点,蓝点表示未加入最小生成树的点. 进行n次循环,每次循环把一个蓝点变为白点,该蓝点应该是与白点相连的最小边权的是当前蓝点中最小的.这样就相当于向生成树中添加了n-1次最小的边,最后得到的一定是最小生成树. 1 #include<cstdio> 2 #include<cstring> 3 #define N 42000 4 using namespace std; 5 int next[N],to

邻接表c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)

graph.c #include <stdio.h> #include <stdlib.h> #include <limits.h> #include "aqueue.h" #define MAX_NUM 100 typedef char node_type; typedef struct arc_node { int pos; int distance; struct arc_node * next; } Arc_node;//保存Node节点的相

poj1861 最小生成树 prim &amp;amp; kruskal

// poj1861 最小生成树 prim & kruskal // // 一个水题,为的仅仅是回味一下模板.日后好有个照顾不是 #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <iostream> using namespace std; const int MAX_N = 1008; const int INF =

无向带权图的最小生成树算法——Prim及Kruskal算法思路

边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以把边上的权值解释为线路的造价.则最小生成树表示使其造价最小的生成树. 构造网的最小生成树必须解决下面两个问题: 1.尽可能选取权值小的边,但不能构成回路: 2.选取n-1条恰当的边以连通n个顶点: MST性质:假设G=(V,E)是一个连通网,U是顶点V的一个非空子集.若(u,v)是一条具有最小权值的

稀疏图(邻接链表),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)

#include<iostream> #include<vector> #include<queue> #include<stack> #include<algorithm> #include<stdio.h> #include<stdlib.h> using namespace std; /* //函数集合声明下,方便查看 void Dijkstra(const denseGraph& dg, int s); v