图的最小生成树
算法简单描述
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来描述所得到的最小生成树。
1 //最小生成树Prim算法 2 public MST getMinimumSpanningTree(int startingIndex){ 3 List<Integer> T = new ArrayList<Integer>();//T是存储添加到生成树的顶点的线性表。 4 T.add(startingIndex); 5 6 int numberOfVertices = vertices.size(); 7 int[] parent = new int[numberOfVertices]; 8 for (int i = 0; i < parent.length; i++) { 9 parent[i] = -1; 10 } 11 int totalWeight = 0; 12 13 List<PriorityQueue<WeightedEdge>> queues = deepClone(this.queues); 14 15 while (T.size() < numberOfVertices) {//直到所有的顶点都被添加到T中 16 int v = -1; 17 double smallestWeight = Double.MAX_VALUE; 18 /** 19 * 对于T中的每一个顶点u, 找到它的与u有最小权值的邻居。顶点u的所有邻居都存储在queue.get(u)中。queue.get(u).peek()返回拥有最小 20 * 权值的连续边。如果邻居已经在T中,删除它(指的是那个权值最小的边), 21 */ 22 for(int u : T){ 23 //检查顶点u是否还有邻边,及最小权值的边是否在T中, 如果是,将这条边删除,继续检查下一条边 24 while(!queues.get(u).isEmpty() &&//明白此处用while的原因 25 T.contains(queues.get(u).peek().v)){ 26 queues.get(u).remove(); 27 } 28 if(queues.get(u).isEmpty()){ 29 continue; 30 } 31 WeightedEdge edge = queues.get(u).peek(); 32 if(edge.weight < smallestWeight){ 33 v = edge.v; 34 smallestWeight = edge.weight; 35 parent[v] = u; 36 } 37 } 38 T.add(v); 39 totalWeight += smallestWeight; 40 } 41 return new MST(startingIndex, parent, T, totalWeight); 42 }