写在前面:
我也是一名java语言的爱好者,仅以此文作为学习的记录,对于文中出现的代码规范,代码格式,算法效率等问题,希望各路大神不吝赐教,在下感激不尽。同是学习的同学也同样希望互相交流,取长补短。
大体上来说,一个无向图G的最小生成树就是由该图的那些连接G的所有顶点的边构成的树,且其总价值最低
Prim算法
计算最小生成树的一种方法是使其连续的一步步的长成,每一步都要把一个节点当作根并往上加边。在算法的任意时刻,我们都可以看到一组已经添加到树上的节点,而其余顶点尚未加到这棵树中。此时,算法在每一时刻都可以通过选择边(u,v)使得(u,v)的值是所有u在树上但v不在树上的边的值中的最小值而找出一个新的顶点添加到这棵树中。
算法设计:
Prim算法基本和求最短路径的Dijsktra算法相同,设计数据类型时,对每个顶点保留dist和path以及一个known指标(表示顶点已知或未知)。这里dist是连接到已知顶点最短边的权,path是导致该顶点改变的最后顶点。
数据类型:
private static int MaxLen = 1000; private static Vertex[] verArray = new Vertex[7]; class Vertex{ public List<Integer> adjacency; public boolean known; public int dist; public Vertex path; public int vname; public Vertex(){ known = false; dist = MaxLen; path = null; } }
算法伪代码
//Prim算法伪代码: /** * Prim(Vertex s){ * s.dist = 0; * while(there is an unknown vertex here){ * Vertex v = the smallest dist vertex; * v.known = true; * for each Vertex w adjacent to v if( !w.known ) { * int dvw = the distance bewteen v and w; * if(dvw<w.dist){ * w.dist = dvw; * w.path = v; * } * } * } * } * */
Java语言实现Prim算法:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class PrimA { /** * @param args */ private static int MaxLen = 1000; private static Vertex[] verArray = new Vertex[7]; class Vertex{ public List<Integer> adjacency; public boolean known; public int dist; public Vertex path; public int vname; public Vertex(){ known = false; dist = MaxLen; path = null; } } //判断是否还有unknown vertex存在 public static boolean Judge(){ for (Vertex v : verArray) { if (v.known==false) { return true; } } return false; } //返回Dist最小的unknown vertex public static Vertex SmallestVertex(){ int Vnum = 0; int value = MaxLen; for(int i=0;i<7;i++){ if((!verArray[i].known)&&(verArray[i].dist<value)){ Vnum = i; value = verArray[i].dist; } } return verArray[Vnum]; } public static void Prim(Vertex s){ s.dist = 0; while(Judge()){ Vertex v = SmallestVertex(); v.known = true; for (Integer i : v.adjacency) { if ((!verArray[v.adjacency.indexOf(i)].known)&&(i<verArray[v.adjacency.indexOf(i)].dist)) { verArray[v.adjacency.indexOf(i)].dist = i; verArray[v.adjacency.indexOf(i)].path = v; } } } } public static void printTree(Vertex s){ System.out.println("最小生成树为:"); for (Vertex v : verArray) { if (v!=s) { System.out.println("V"+v.vname+"-----"+"V"+v.path.vname+" "+"边权值为"+v.adjacency.get(v.path.vname)); } } } public static void main(String[] args) { // TODO Auto-generated method stub //初始化 verArray[0] = new PrimA().new Vertex(); verArray[1] = new PrimA().new Vertex(); verArray[2] = new PrimA().new Vertex(); verArray[3] = new PrimA().new Vertex(); verArray[4] = new PrimA().new Vertex(); verArray[5] = new PrimA().new Vertex(); verArray[6] = new PrimA().new Vertex(); verArray[0].adjacency = new ArrayList<Integer>(Arrays.asList(0,2,4,1,MaxLen,MaxLen,MaxLen)); verArray[0].vname = 0; verArray[1].adjacency = new ArrayList<Integer>(Arrays.asList(2,0,MaxLen,3,10,MaxLen,MaxLen)); verArray[1].vname = 1; verArray[2].adjacency = new ArrayList<Integer>(Arrays.asList(4,MaxLen,0,2,MaxLen,5,MaxLen)); verArray[2].vname = 2; verArray[3].adjacency = new ArrayList<Integer>(Arrays.asList(1,3,2,0,7,8,4)); verArray[3].vname = 3; verArray[4].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,10,MaxLen,7,0,MaxLen,6)); verArray[4].vname = 4; verArray[5].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,5,8,MaxLen,0,1)); verArray[5].vname = 5; verArray[6].adjacency = new ArrayList<Integer>(Arrays.asList(MaxLen,MaxLen,MaxLen,4,6,1,0)); verArray[6].vname = 6; //起点从v0开始 Prim(verArray[0]); printTree(verArray[0]); } }
运行结果: