圖+鄰接矩陣+最小生成樹

/**
 * 文件名:AdjacencyMatrix.java
 * 所在包:Graph
 * 日期:2013-12-31 上午9:27:47
 * 版本信息:version V1.0
 * Copyright Corporation 2013
 * 版權全部: 
 *
 */  

package Graph;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

/**
 *
 * 項目名稱:jobdu
 * 類名稱:AdjacencyMatrix
 * 類描述:鄰接矩陣 = 順序表(存儲頂點信息) + 二維數組(表示頂點之間的鄰接關係)
 * 建立人:黃傳聰
 * 建立時間:2013-12-31 上午9:27:47
 * 修改人:
 * 修改時間:
 * 修改備註:
 * @version
 */
public class AdjacencyMatrix {

	/** 頂點數量   */
	private int n;
	/** 頂點數組   */    
	private int[] vertexes;
	/** 二維數組,表示頂點之間的鄰接關係 0表示無關係  */    
	private int[][] matrix;
	/**  是不是無向圖:true ;有向圖:false  */    
	private boolean flag ;
	//各個節點的父節點
	private int[] fathers ;
	public AdjacencyMatrix() {
		//默認爲10
		this(10,true);
		
	}
	public AdjacencyMatrix(int n, boolean flag) {
		this.n = n;
		this.flag = flag;
		vertexes = new int[n];
		matrix = new int[n][n];
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				matrix[i][j] = Integer.MAX_VALUE;
			}
		}
		
		fathers = new int[n];
	}
	
	/**
	 * 方法名稱:init()
	 * 方法描述:開始填充矩陣
	 * @param  
	 * @return String    
	 * @Exception 
	 */
	public void init(){
		int head , tail, w = 0;
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("請輸入 邊的起始和終止頂點序號 和 邊的權值: ************");
		while(scanner.hasNext()){
			
			head = scanner.nextInt();
			tail = scanner.nextInt();
			w = scanner.nextInt();
			
			if(head==0 && tail==0 && w == 0){
				System.out.println("********輸入完畢********************");
				break;
			}
			
			matrix[head-1][tail-1] = w;
			if(flag){
				matrix[tail-1][head-1] = w;
			}
		}
		
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				System.out.print(matrix[i][j] + " ");
			}
			System.out.println();
		}
	}

	public int[][] getMatrix() {
		return matrix;
	}
	public void setMatrix(int[][] matrix) {
		this.matrix = matrix;
	}
	public int[] getVertexes() {
		return vertexes;
	}
	public void setVertexes(int[] vertexes) {
		this.vertexes = vertexes;
	}
	/**
	 * 方法名稱:main()
	 * 方法描述:
	 * @param  
	 * @return String    
	 * @Exception 
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n = 6;
		//使用鄰接矩陣存儲一個無向圖
		AdjacencyMatrix adjacencyMatrix = new AdjacencyMatrix(n,true);
		Scanner scanner = new Scanner(System.in);
		int[] vertexes = new int[n];
		System.out.println("請輸入頂點節點: ");
		for(int i=0;i<n;i++){
			vertexes[i] = scanner.nextInt();
		}
		
		adjacencyMatrix.setVertexes(vertexes);
		adjacencyMatrix.init();
		/*for(int i=0;i<adjacencyMatrix.n;i++){
			for(int j=0;j<adjacencyMatrix.n;j++){
				System.out.print(adjacencyMatrix.getMatrix()[i][j] + " ");
			}
			
			System.out.println();
		}
		
		int[] result = adjacencyMatrix.prim(2);
		for(int a : result){
			System.out.print((a+1) + " -> ");
		}*/
		
		adjacencyMatrix.kruscal();

	}

	
	/**
	 * 方法名稱:prim()
	 * 方法描述:最小生成樹,prim 算法實現:對頂點進行遍歷,適用於稠密圖,時間複雜度o(n*n)
	 * @param  begin: 開始遍歷的節點
	 * 測試數據:
	 * 1 2 3 4 5 6
		1 2 6
		1 3 1
		1 4 5
		2 5 3
		2 3 5
		3 4 5
		3 5 6 
		3 6 4 
		4 6 2
		5 6 6
		0 0 0
	 * @return String    
	 * @Exception 
	 */
	public int[] prim(int begin){
		int index = 0;
		//結果
		int[] result = new int[n];
		/*兩個頂點之間的最小距離*/
		int[] lowCost = new int[n];
		/*記錄頂點是否被選中, 默認爲未選中*/
		int[] closet = new int[n];
		//標記節點選中
		closet[begin] = 1;
		result[index++] = begin;
		for(int i=0;i<n;i++){
			lowCost[i] =  matrix[begin][i];
		}
		
		//從餘下的n-1的節點中查找節點 
		for(int j=1;j<n;j++){
			//從0-i中選出一個路徑最小的節點,加入到選中節點中
			int min = Integer.MAX_VALUE;
			int k = 0; //記錄最小值得位置
			for(int i=0;i<n;i++){
				if(lowCost[i]<min && closet[i] == 0 && lowCost[i] != 0){
					min = lowCost[i];
					k = i;
				}
			}
			//選中節點
			closet[k] = 1;
			lowCost[k] = 0;
			result[index++] = k;
			//修改lowCost中的值
			for(int l=0;l<n;l++){
				if(closet[l]==0 && lowCost[l] > matrix[k][l]&& lowCost[l] != 0){
					lowCost[l] = matrix[k][l];
				}
			}
			
		}
		return result;
	}
	
	public void prim(){
		int[] lowCost = new int[n];
		int[] closeSet = new int[n];
		
		int i ,j, k, min;
		
		for(i=1;i<n;i++){
			lowCost[i] = matrix[0][i];
			closeSet[i] = 1;
		}
		
		for(i=1;i<n;i++){
			min = Integer.MAX_VALUE;
			k = 0;
			for(j=1;j<n;j++){
				if(lowCost[j]<min && lowCost[j] != 0){
					min = lowCost[j];k = j;
				}
			}
			
			lowCost[k] = 0;
			System.out.println(closeSet[k]);
			closeSet[k] = 0;
			for(j=1;j<n;j++){
				if(matrix[k][j]<lowCost[j] && matrix[k][j] != 0){
					lowCost[j] = matrix[k][j];
					closeSet[j] = k;
				}
			}
		}
//		for(int out : closeSet){
//			System.out.println(out);
//		}
	}
	
	/**
	 * 方法名稱:kruscal()
	 * 方法描述:kruscal算法,能夠使用並查集進行操做
	 * @param  
	 * @return String    
	 * @Exception 
	 */
	public void kruscal(){
		final class Edge{
			//設置邊的兩個頂點和權值
			private int from;
			private int end;
			private int weight;
			public Edge(){}
			public Edge(int from, int end, int weight){
				this.from = from;
				this.end = end;
				this.weight = weight;
			}
		}
		
		//初始化其父節點爲其自己
		//頂點數組中存放的數據爲 1, 2 ,3 。。
		//因 而在使用時,須要減一
		for(int i=0;i<n;i++){
			fathers[vertexes[i]-1] = vertexes[i] - 1;
		}
		List<Edge> edges = new ArrayList<Edge>();
		//構建list
		//若是是無向圖,只需構建一側
		//無向圖
		Edge edge = null;
		if(flag){
			
			for(int i=0;i<n;i++){
				for(int j=0;j<=i;j++){
					if(matrix[i][j] != Integer.MAX_VALUE && matrix[i][j] != 0){
						edge = new Edge(i, j, matrix[i][j]);
						edges.add(edge);
					}
				}
			}
		}else{
			for(int i=0;i<n;i++){
				for(int j=0;j<n;j++){
					if(matrix[i][j] != Integer.MAX_VALUE && matrix[i][j] != 0){
						edge = new Edge(i, j, matrix[i][j]);
						edges.add(edge);
					}
				}
			}
		}
		
		//對edges按照權值排序
		Collections.sort(edges, new Comparator<Edge>() {

			@Override
			public int compare(Edge e1, Edge e2) {
				// TODO Auto-generated method stub
				if(e1.weight - e2.weight > 0){
					return 1;
				}else if(e1.weight - e2.weight < 0){
					return -1;
				}else{
					return 0;
				}
			}
		});
		
		//對每條邊的兩個頂點設置父頂點
		for(Edge e : edges){
			
			int a = getFather(e.from);
			int b = getFather(e.end);
			if(a != b){
				fathers[b] = a;
				System.out.println((e.from+1) + " -> " + (1+e.end));
			}
		}
		
	}
	
	private int getFather(int x){
		return (x == fathers[x]) ? x : (fathers[x]=getFather(fathers[x]));
	}
}
相關文章
相關標籤/搜索