普里姆算法

import java.io.IOException;
import java.util.Scanner;

public class Graph {
	private char[] vertex;    //顶点集合
	private int[][] matrix;   //邻接矩阵
	private static final int INF = Integer.MAX_VALUE; //最大值
	
	/**
	 * 创建图
	 */
	public Graph() {
		Scanner sca = new Scanner(System.in);
		int vertexNum = sca.nextInt();       //顶点数
		int matrixNum = sca.nextInt();       //边数
		vertex = new char[vertexNum];
		
		//初始化顶点
		for(int i = 0; i < vertexNum; i++) {
			vertex[i] = readChar();
		}
		
		//初始化 边 的权值
		matrix = new int [vertexNum][vertexNum];
		for(int i = 0; i < vertexNum; i++) 
			for(int j = 0; j < vertexNum; j++)
				matrix[i][j] = 	(i == j) ?  0 : INF;
		//根据用户输入的边的信息:初始化边
		for(int i = 0; i < matrixNum; i++) {
			char start = readChar();
			char end   = readChar();
			int weight = sca.nextInt();
			int startInedx = getLocation(start);
			int endIndex   = getLocation(end);
			if(startInedx == -1 || endIndex == -1) return;
			matrix[startInedx][endIndex] = weight;
			matrix[endIndex][startInedx] = weight;
		}
		sca.close();
	}
	/**
	 * 返回字符的位置
	 */
	private int getLocation(char c) {
		for(int i = 0; i < vertex.length; i++) 
			if(vertex[i] == c) return i;
		return -1;
	}
	
	/**
	 * 读取一个输入字符
	 * @return
	 */
	private char readChar() {
		char ch = '0';
		do {
			try {
				ch = (char)System.in.read();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}while(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));
		return ch;
	}
	/**
	 * 打印矩阵队列图
	 */
	public void print() {
		for(int i = 0; i < vertex.length; i++)
			for(int j = 0; j < vertex.length; j++)
				System.out.printf("%10d", matrix[i][j]);
		    System.out.println();
	}
	
    public void prim(int start) {
    	int num = vertex.length;     //顶点个数 
    	int index = 0;               //prim最小的索引,即prims数组的索引
    	char[] prims = new char[num];//prim最小树的结果
    	int[] weights = new int[num];//顶点间边的权值
    	
    	//prim最小生成树中的第一个数是 "图中第start个顶点",因为是从strat开始的
    	prims[index++] = vertex[start];
    	
    	//初始化"顶点的权值数组"
    	//将每个顶点的权值初始化为第start个顶点 到"该顶点"的权值
    	for(int i = 0; i < num; i++) 
    		weights[i] = matrix[start][i];
    	//自己到自己的路径为0
    	weights[start] = 0;
    	for(int i = 0; i < num; i++) {
    		//由于从start开始的,因此不再需要再第start个顶点进行处理
    		if(start == i) continue;
    		int j = 0;
    		int k = 0;
    		int min = INF;
    		//在未被加入到最小生成树的顶点中,找出权值最小的顶点
    		while(j < num) {
    			//若weights[j]=0,意味着"第j个节点已经被排序过"(或者说已经加入了最小生成树中)
    			if(weights[j] != 0 && weights[j] < min) {
    				min = weights[j];
    				k = j;
    			}
    			j++;
    		}
    		// 经过上面的处理后,在未被加入到最小生成树的顶点中,权值最小的顶点是第k个顶点。
            // 将第k个顶点加入到最小生成树的结果数组中
    		prims[index++] = vertex[k];
    		//将"第k个顶点的权值"标记为0,意味着第k个顶点已经排序过了(或者说已经加入了最小树结果中)
    		weights[k] = 0;
    	    // 当第k个顶点被加入到最小生成树的结果数组中之后,更新其它顶点的权值。
    		for(j = 0; j < num; j++) {
    			//当第j个节点没有被处理,并且需要更新的时才更新
    			if(weights[j] != 0 && matrix[k][j] < weights[j])
    				weights[j] = matrix[k][j];
    		}
    	}
    	//计算最小生成树的权值
		int sum = 0;
		for(int i = 1; i < index; i++) {
			int min = INF;
			//获取prims[i]在matrix中的位置
			int n = getLocation(prims[i]);
			// 在vertex[0...i]中,找出到j的权值最小的顶点
			for(int j = 0; j < i; j++) {
				int m = getLocation(prims[j]);
				if(matrix[m][n] < min) {
					min = matrix[m][n];
				}
			}
			sum +=min;
		}
		//打印最小生成树
    	System.out.print("PRIM(" + vertex[start] + ") = " +  sum);
    	for(int i = 0; i < index; i++)
    		System.out.print(prims[i]);
    	System.out.println();
		
    }
    public static void main(String[] args) {
		Graph ga = new Graph();
		ga.prim(0);
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章