图的最小生成树kruskal算法总结

    xiaoxiao2021-03-25  53

    kruskal算法的思想

    假如N={V,{E}}是连通网,那么最小生成树的初始状态是由V个顶点自成连通分量构成的一片森林。在E中选择权值最小的边,当该边对应的两个顶点在不同分量时,则将该边加入到最小生成树中,否则的舍去,再选择下一条代价最小的边,如此循环,直到所有的连通分量连接变成一个连通分量为止。

    看看具体代码

    public void minSpanTree_kurskal(Edges[] edges){ //edges已按照权值大小进行了非递减排序 Integer parent[] = new Integer[edges.length]; int n,m; for(int i=0;i<edges.length;i++){ //初始化parent[]全部元素为0; parent[i] = 0; } for(int i=0;i<edges.length;i++){ n = find(parent,edges[i].begin); //寻找edges[i].begin所在连通分量的根顶点 m = find(parent,edges[i].end); //寻找edges[i].end所在连通分量的根顶点 if(n!=m){ // 如果根结点不同说明dges[i].begin和dges[i].end在不同分量上 parent[n] = m; System.out.println("begin="+edges[i].begin+","+"end="+edges[i].end+","+"weight="+edges[i].weight); } } } private int find(Integer[] parent, int f) { while(parent[f]>0) f = parent[f]; return f; }

    这里存在一个问题:如何判断2个顶点在同一个连通分量?

    每个连通分量上都有一个顶点代表整个连通分量,我们把它叫做根顶点,也就是通过find()方法我们可以找到该顶点所在连通分量的根顶点,如果两个顶点的根顶点相同,则代表这两个顶点在同一个连通分量上,反之则不是。

    算法运行详解

    1.用边集数组存储图,然后再按照权值大小进行非递减排好序,结果如下图所示

    2.初始化parent[],结果如下图

    值全部为0也就代表每一个顶点自称一个连通分量

    3.取权值最小的边

    4.调用find方法得到顶点所在连通分量的根顶点

    注:其实每个连通分量的全部顶点可以看成类似树,但此树的边总是从子结点指向父节点,最后树的根即为根顶点,

    如当循环到edges[6]时,有如下图所示结果

    如上图所示,通过parent[]数组可以画出两个类似树的连通分量,其中7和6分别为森林中两个不同的连通分量的根顶点。如要判断顶点5所在连通分量的根顶点是什么,图中可看到5的父结点为8,8的父节点为6,6的父结点为空,说明6即为连通分量的根节点。

    5.如果两个顶点的根顶点不同,说明两个顶点在不同的连通分量上,将该边加入最小生成树中,否则舍弃。

    6.取最小权值的边不断循环......

    转载请注明原文地址: https://ju.6miu.com/read-40073.html

    最新回复(0)