您的位置:首页 > 其它

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

2011-11-19 11:21 330 查看
算法设计: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
;
	}
	
	//查找到达指定顶点的边
	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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: