最近研究图论的算法,接触到构建最小生成树的prim算法(当然还有其他方法:Kruskal算法也可以构建),所以记录一下。
首先,什么是最小生成树?
百度百科给出的定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。
概念有点抽象,下面用一幅图来演示说明。
那么如何构建一棵最小生成树呢?有下面三个步骤:
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:U={x},其中x为集合V中的任一节点(起始点),T={},为空;
3).重复下列操作,直到U=V:
a、在集合E中选取全值最小的边<u,v>,其中u为集合U中的元素,而v不在U集合里面,
并且v属于V(如果存在多条满足前述条件,即具有相同权值的边,则可以任意选取其中之一);
b、将v加入集合U中,将<u,v>边加入集合T中;
4).输出:使用集合U和T,来描述所得到的最小生成树。
下面用图来展示上面给出的步骤:
代码如下:
/**
* prim最小生成树
*/
public void prim(){
char[] code={'A','B','C','D','E','F','G'};
ArrayList<Integer> u =new ArrayList<>();
//默认A是第一个节点
u.add(3);
//T{}
ArrayList<int[]> t =new ArrayList<>();
//重复直到U=T
while(u.size()!=this.verticeSize){
int tmp=BGraph.MAXVERTICESIZE;
int tmpi=0;
int pi=0,pj=0;
//找最短距离
for (int i = 0; i < u.size(); i++) {
tmpi=u.get(i);
for (int j = 0; j < this.verticeSize; j++) {
if(this.verticesEde[tmpi][j]!=0&&this.verticesEde[tmpi][j]<tmp){
tmp=this.verticesEde[tmpi][j];
pi=tmpi;
pj=j;
}
}
}
if(tmp!=BGraph.MAXVERTICESIZE){
//找到最短距离
t.add(new int[]{pi,pj,verticesEde[pi][pj]});
u.add(pj);
//代表已经访问过
this.verticesEde[pi][pj]=0;
this.verticesEde[pj][pi]=0;
}
}
int sum=0;
for (int i = 0; i < t.size(); i++) {
int[] nums=t.get(i);
sum+=nums[2];
System.out.println(code[nums[0]]+" -> "+code[nums[1]]);
}
System.out.println("最小生成树总代价:"+sum);
}
//测试代码
Graph graph=new Graph(7);
int[] a0={0,50,60,MAXVERTICESIZE,MAXVERTICESIZE,MAXVERTICESIZE,MAXVERTICESIZE};
int[] a1={50,0,MAXVERTICESIZE,65,40,MAXVERTICESIZE,MAXVERTICESIZE};
int[] a2={60,MAXVERTICESIZE,0,52,MAXVERTICESIZE,MAXVERTICESIZE,45};
int[] a3={MAXVERTICESIZE,65,52,0,50,30,42};
int[] a4={MAXVERTICESIZE,40,MAXVERTICESIZE,50,0,70,MAXVERTICESIZE};
int[] a5={MAXVERTICESIZE,MAXVERTICESIZE,MAXVERTICESIZE,30,70,0,MAXVERTICESIZE};
int[] a6={MAXVERTICESIZE,MAXVERTICESIZE,45,42,MAXVERTICESIZE,MAXVERTICESIZE,0};
graph.verticesEde[0]=a0;
graph.verticesEde[1]=a1;
graph.verticesEde[2]=a2;
graph.verticesEde[3]=a3;
graph.verticesEde[4]=a4;
graph.verticesEde[5]=a5;
graph.verticesEde[6]=a6;
graph.prim();
运行结果:
A -> B
B -> E
E -> D
D -> F
D -> G
G -> C
最小生成树总代价:257