自己动手写数据结构总目录:https://blog.csdn.net/qq_31709249/article/details/102962377
该文章的源代码仓库为:
一、相关定义
- 图的生成树: 一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
- 最小生成树: 所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
最小生成树的生成算法有两种:Prim算法和Kruskal算法。介绍如下:
二、Prim算法
1.算法流程
Prim算法的原理如下:
- 1.输入:一个加权连通图。当中顶点集合为V,边集合为E;
- 2.初始化:Vnew = {x},当中x为集合V中的任一节点(起始点),Enew = {},为空;
- 3.反复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,当中u为集合Vnew中的元素。而v不在Vnew集合当中。而且v∈V(如果存在有多条满足前述条件即具有同样权值的边,则可随意选取当中之中的一个);
b.将v增加集合Vnew中,将<u, v>边增加集合Enew中。 - 4.输出:使用集合Vnew和Enew来描写叙述所得到的最小生成树。
找个图来说明(图来自这篇博客):
2.代码实现
网上经典的写法都是利用邻接矩阵来实现Prim算法的,因为邻接矩阵能非常方便的获取到一个顶点的相邻顶点。网上的写法都差不多,我这里也用邻接矩阵的经典方法实现,重点其中各个变量的意义。代码如下:
public class AdjMatrixGraph<T> extends Graph<Integer>{
public static int INFINITY=Integer.MAX_VALUE/2;
protected int[][] matrix;//邻接矩阵
protected String[] vertexNames;//顶点名
AdjMatrixGraph(int vertexNum){
super(vertexNum);
vertexNames=new String[vertexNum];
matrix=new int[vertexNum][vertexNum];
//将邻接矩阵中的值初始化为INFINITY
for (int i=0;i<vertexNum;i++)
for (int j=0;j<vertexNum;j++)
matrix[i][j]=INFINITY;
}
public AdjMatrixGraph(int[][] edges, String[] vertexNames){
this(vertexNames.length);
this.vertexNames=vertexNames;
for (int i=0;i<edges.length;i++)
addEdge(edges[i][0],edges[i][1],edges[i][2]);
}
@Override
protected void addEdge(int headIndex, int tailIndex, Integer weight) {
super.addEdge(headIndex, tailIndex, weight);
this.matrix[headIndex][tailIndex]=(Integer) weight;
}
/**
* 利用prim算法求图的最小生成树
*/
public void prim(){
System.out.println