普里姆算法

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);
	}
}

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