带权图是实际情况中经常使用的,如城市道路,etl优化等等。
在带权图中经常遇到的问题就是生成最小生成树,就是加权总值最小的路径,这里用prime算法实现
prim算法的总思路
/**
* 生成最小生成树
* 将顶点放到树集合中,重复一下操作
* 1.找到最新的vertex到其他vertex的所有edge,其他vertex不能在树集合中,把这些edge放到优先队列中
* 2.找到权值最小的边,把edge和edge所到达的vertex放到树集合中
*/
prim算法的过程示意图:这里贴一个邮电大学的
prim算法代码,java实现:
package com.Construction.DiscrectGraph;
import java.io.ObjectOutputStream.PutField;
public class Graph {
/**
* max vertx number
*/
private final int MAX_VERTX = 20;
/**
* max distance value
*/
private final int INFINITY = 1000000;
/**
* node list
*/
private Vertex vertexList[];
/**
* adjacency matrix
*/
private int adjMat[][];
/**
* graph node number
*/
private int nVerts;
/**
* prime tree number
*/
private int nTree;
/**
* current tree node
*/
private int currentVert;
private PriorityQ priorityQueue;
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;
}
}
priorityQueue = new PriorityQ();
}
/**
* 添加元素
* @param label
*/
public void addVertex(char label){
//添加元素,并将计数器加一
vertexList[nVerts++] = new Vertex(label);
}
/**
* 添加边
* @param sv
* @param dv
* @param dis
*/
public void addEdge(int sv,int dv,int dis){
adjMat[sv][dv] = dis;
adjMat[dv][sv] = dis;
}
/**
* 生成最小生成树
* 将顶点放到树集合中,重复一下操作
* 1.找到最新的vertex到其他vertex的所有edge,其他vertex不能在树集合中,把这些edge放到优先队列中
* 2.找到权值最小的边,把edge和edge所到达的vertex放到树集合中
*/
public void mstw(){
currentVert = 0;
while (nTree < nVerts -1) {
vertexList[currentVert].isInTree = true;//步骤2,放到树中
nTree ++;
for (int i = 0; i < nVerts; i++) {
if(i == currentVert) continue; // visit other graph node
if(vertexList[i].isInTree) continue;//visit other graph don't contain in tree -- to avoid connect unneccessary node
int dis = adjMat[currentVert][i];
if (dis == INFINITY) continue;
putInPQ(i, dis);
}
if (priorityQueue.getSize() == 0) {
return;
}
Edge currentMinEdge = priorityQueue.removeMin();
int sVert = currentMinEdge.srcVert;
currentVert = currentMinEdge.destVert;
System.out.println(vertexList[sVert].label);
System.out.println(vertexList[currentVert].label);
System.out.println(" ");
}
for (int i = 0; i < nVerts; i++) {
vertexList[i].isInTree = false;
}
}
/**
* 将循环操作1中的edge,放入优先队列中
* 优先队列中,到一个目的的边是唯一滴,所有当已经有老边了,需要比较替代
* @param vertex
* @param dis
*/
public void putInPQ(int vertex,int dis){
int index = priorityQueue.find(vertex);
if(index != -1){
Edge tempEdge = priorityQueue.peek(index);
int oldDis = tempEdge.distance;
if(oldDis > dis){
priorityQueue.remove(index);
Edge theEdge = new Edge(currentVert, vertex, dis);
priorityQueue.insert(theEdge);
}
}else{
Edge theEdge = new Edge(currentVert, vertex, dis);
priorityQueue.insert(theEdge);
}
}
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();
}
}