普里姆算法按照以下步骤逐步扩大树中所含顶点的数目,直到遍及连通图的所有顶点:
- 输入:一个加权连通图,其中顶点集合为V,边集合为E;
- 初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {};
- 重复下列操作,直到Vnew = V:
- 在集合E中选取权值最小的边(u, v),其中u为集合Vnew中的元素,而v则不是(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
- 将v加入集合Vnew中,将(u, v)加入集合Enew中;
- 输出:使用集合Vnew和Enew来描述所得到的最小生成树。
实现:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Prim {
public static List<Vertex> vertexList = new ArrayList<Vertex>();// 结点集
public static List<Edge> EdgeQueue = new ArrayList<Edge>();// 边集
public static List<Vertex> newVertex = new ArrayList<Vertex>();// 已经 访问过的结点
public static void main(String[] args) {
primTree();
}
/**
*
* 构建图
*
**/
public static void buildGraph() {
Vertex v1 = new Vertex("a");
Prim.vertexList.add(v1);
Vertex v2 = new Vertex("b");
Prim.vertexList.add(v2);
Vertex v3 = new Vertex("c");
Prim.vertexList.add(v3);
Vertex v4 = new Vertex("d");
Prim.vertexList.add(v4);
Vertex v5 = new Vertex("e");
Prim.vertexList.add(v5);
addEdge(v1, v2, 6);
addEdge(v1, v3, 7);
addEdge(v2, v3, 8);
addEdge(v2, v5, 4);
addEdge(v2, v4, 5);
addEdge(v3, v4, 3);
addEdge(v3, v5, 9);
addEdge(v5, v4, 7);
addEdge(v5, v1, 2);
addEdge(v4, v2, 2);
}
/**
*
* 构建边
*
**/
public static void addEdge(Vertex a, Vertex b, int w) {
Edge e = new Edge(a, b, w);
Prim.EdgeQueue.add(e);
}
/**
*
* prim算法寻找最小生成树的实现
*
**/
public static void primTree() {
buildGraph();
Vertex start = vertexList.get(0);
newVertex.add(start);
for (int n = 0; n < vertexList.size(); n++) {
Vertex temp = new Vertex(start.key);
Edge tempedge = new Edge(start, start, 1000);
for (Vertex v : newVertex) {
for (Edge e : EdgeQueue) {
//如果边开始结点等于当前结点,并且边的终点等没有被访问过
if (e.start == v && !containVertex(e.end)) {
//得出最小权值
if (e.key < tempedge.key) {
temp = e.end;
tempedge = e;
}
}
}
}
newVertex.add(temp);
}
Iterator it = newVertex.iterator();
while (it.hasNext()) {
Vertex v = (Vertex) it.next();
System.out.println(v.key);
}
}
/**
*
* 判断传入的结点是否是已经被访问过的结点
*
**/
public static boolean containVertex(Vertex vte) {
for (Vertex v : newVertex) {
if (v.key.equals(vte.key))
return true;
}
return false;
}
}
/**
*
* 结点类
*
**/
class Vertex {
String key; //结点名
Vertex(String key) {
this.key = key;
}
}
/**
*
* 边类
*
**/
class Edge {
Vertex start; //边的开始结点
Vertex end; //边的终点结点
int key; //边的权值
Edge(Vertex start, Vertex end, int key) {
this.start = start;
this.end = end;
this.key = key;
}
}
声明:本代码不是自己编写,来自维基百科,本人只是做了点修改。