Prim算法的基本思想就是假设G=(V,E)是一个无向带权图,生成的最小生成树为MinT=(V,T),其中V为顶点的集合,T为边的集合,构造步骤如下:
1)初始化:U={u0},T={ }。其中U为一个新设置的顶点的集合,初始U时只含有顶点u0,这里假设在构造最小生成树时,从顶点u0出发;
2)对所有u∈U,v∈V-U(其中u,v表示顶点的集合)的边(u,v)中,找一条权最小的边(u",v"),将这条边加入到集合T中,将顶点v"加入到集合U中;
3)如果U=V,则算法结束;否则重复(2)、(3)步。
最后得到的最小生成树MinT=<V,T>,其中T为最小生成树的边的集合。
1、首先创建无向带权图的邻接矩阵:
public class GraphA {
int vex[] = new int[5];
int arcs[][] = new int[5][5];
int vexnum = 5, arcnum = 6;
public GraphA() {
//初始化顶点
for (int i = 0; i < vexnum; i++) {
vex[i] = i;
}
//初始化边(权值)
for (int i = 0; i < vexnum; i++) {
for (int j = 0; j < vexnum; j++) {
arcs[i][j]=9999;
}
}
arcs[0][1]=50;
arcs[0][3]=40;
arcs[0][4]=20;
arcs[1][0]=50;
arcs[1][2]=10;
arcs[2][1]=10;
arcs[2][3]=20;
arcs[2][4]=30;
arcs[3][0]=40;
arcs[3][2]=20;
arcs[4][0]=20;
arcs[4][2]=30;
}
}
创建一个数组用来保存最小边的权值:
public class Closedge {
int adjvex;
int lowcost;
}
下面是Prim算法构造最小生成树的代码:
public class Prim {
public static void main(String[] args) {
GraphA graphA = new GraphA();
Prim(graphA,0);
}
/**
* 最小生成树
*
* @param graphA
* @param u
*/
public static void Prim(GraphA graphA, int u) {
Closedge closedge[] = new Closedge[5];
int v, k, j, min;
int nearvex[] = new int[5];
//初始化closedge[],该数组用来保存从u出发,到所有顶点的权值.
for (v = 0; v < graphA.vexnum; v++) {
closedge[v] = new Closedge();
nearvex[v] = v;
if (v != u) {
closedge[v].lowcost = graphA.arcs[u][v];
closedge[v].adjvex = u;
}
}
//由于u是U集合的第一个顶点
closedge[u].lowcost = 9999;
nearvex[u] = -1;
for (k = 0; k < graphA.vexnum; k++) {
min = closedge[k].lowcost;
v = k;
//查找最小权值
for (j = 0; j < graphA.vexnum; j++) {
if( closedge[j].lowcost < min ){
min = closedge[j].lowcost;
v = j;
}
}
System.out.println(closedge[v].adjvex +","+ v +" \n");
closedge[v].lowcost = 9999;
nearvex[v] = -1;
//如果U到V-U有更小的权值,则交换权值
for (j = 0; j < graphA.vexnum; j++) {
if( nearvex[j] !=-1 && graphA.arcs[v][j] < closedge[j].lowcost ){
closedge[j].lowcost = graphA.arcs[v][j];
closedge[j].adjvex = v;
}
}
}
}
}