图论-带权图的最小生成树(Prim)算法

来源:互联网 发布:什么网络游戏支持mac 编辑:程序博客网 时间:2024/05/04 22:32

算法设计:Prim算法从顶点开始着手。

从一个顶点开始,然后放入到树的集合中,然后重复做如下事情:

    (1)、找最新的顶点到其他顶点的所有边,这些顶点不能在树的集合中,把这些放入优先级队列。

    (2)、找到权值最小的边把它和它所到达的顶点放入树的集合中。

重复上述操作直到所有的顶点都在树中,程序结束。


Graph_mstw.java

package com.mapbar.structure;/** *  * Class Graph_mstw.java *  * Description 带权图的最小生成树算法 * 总原则:选择从已经处理过的点到未处理过的点的费用最低的边。 * Company mapbar *  * author Chenll E-mail:  *  * Version 1.0 *  * Date 2012-10-9 上午11:25:06 */// 定义边class Edge {public int srcVert; // 源点public int destVert; // 目的点public int distance; // 距离public Edge(int sv, int dv, int d) {this.srcVert = sv;this.destVert = dv;this.distance = d;}}// 定义节点class Vertex {public char label;public boolean isInTree;public Vertex(char l) {this.label = l;isInTree = false;}}//定义优先级队列,//找到新的顶点到其它顶点所有边,这些顶点不能在树的集合中,放入优先级队列,找到费用最少的,把它和它所到达的顶点放入树的集合中class PriorityQ{private final int SIZE = 20;private Edge[] queArray;private int size;public PriorityQ(){queArray = new Edge[SIZE];size = 0;}//新增public void insert(Edge item){int j;for(j = 0; j<size; j++){if(item.distance>=queArray[j].distance){//从大到小排序break;}}//后移for(int i = size-1; i>=j; i--){queArray[i+1] = queArray[i];}queArray[j] = item;size ++;}//删除最小的public Edge removeMin(){return queArray[--size];}//删除第N个public void removeN(int n){//前移for(int i = n; i<size-1; i++){queArray[i] = queArray[i+1];}size --;}public int size(){return size;}public boolean isEmpty(){return size == 0;}//获取第N个边public Edge peekN(int n){return queArray[n];}//查找到达指定顶点的边public int find(int vIndex){for(int i = 0; i<size; i++){if(queArray[i].destVert == vIndex){return i;}}return -1;}}class Graph {private final int MAX_VERTX = 20; // 节点数private final int INFINITY = 1000000; // 最远距离private Vertex vertexList[];private int adjMat[][]; //邻接矩阵private int nVerts; //记录顶点的个数private int nTree; //记录树中顶点的个数private int currentVert; //当前顶点private PriorityQ thePQ; //优先级队列public Graph() {vertexList = new Vertex[MAX_VERTX];adjMat = new int[MAX_VERTX][MAX_VERTX];nVerts = 0;// 初始化矩阵for (int i = 0; i < MAX_VERTX; i++) {for (int j = 0; j < MAX_VERTX; j++) {adjMat[i][j] = INFINITY;}}thePQ = new PriorityQ(); }// 添加顶点public void addVertex(char label) {vertexList[nVerts++] = new Vertex(label);}// 添加边public void addEdge(int sv, int dv, int dis) {adjMat[sv][dv] = dis;adjMat[dv][sv] = dis;}//最小生成树public void mstw(){currentVert = 0;while(nTree < nVerts-1) {vertexList[currentVert].isInTree = true;nTree ++;for(int i = 0; i< nVerts; i++){//源点和终点相同if(i == currentVert) continue;//终点已经在树里面if(vertexList[i].isInTree) continue;//源点和终点没有边int dis = adjMat[currentVert][i];if(dis == INFINITY) continue;//加入当前点和终点的边到队列putInPQ(i, dis);}if(thePQ.size() == 0){return;}Edge theEdge = thePQ.removeMin();int sVert = theEdge.srcVert;currentVert = theEdge.destVert;System.out.print(vertexList[sVert].label);System.out.print(vertexList[currentVert].label);System.out.print(" ");}//重新设置for(int j = 0; j<nVerts; j++){vertexList[j].isInTree = false;}}public void putInPQ(int vertex,int dis){int index = thePQ.find(vertex);if(index!=-1){//检查老边是否有比新边更小的成本,如果新边成本比老边少,需要删除老边,把新边放入Edge tempEdge = thePQ.peekN(index);int oldDis = tempEdge.distance;if(oldDis > dis){ thePQ.removeN(index);Edge theEdge = new Edge(currentVert,vertex,dis);thePQ.insert(theEdge);}} else {Edge theEdge = new Edge(currentVert,vertex,dis);thePQ.insert(theEdge);} }}public class Graph_mstw {public static void main(String[] args){Graph g = new Graph();g.addVertex('A');g.addVertex('B');g.addVertex('C');g.addVertex('D');g.addVertex('E');g.addVertex('F');g.addEdge(0, 1, 6);g.addEdge(0, 3, 4);g.addEdge(1, 2, 10);g.addEdge(1, 3, 7);g.addEdge(1, 4, 7);g.addEdge(2, 3, 8);g.addEdge(2, 4, 5);g.addEdge(2, 5, 6);g.addEdge(3, 4, 12);g.addEdge(4, 5, 7);g.mstw();}}

输出结果:AD AB BE EC CF