图+邻接矩阵+最小生成树

/**
 * 文件名: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]));
	}
}
相关文章
相关标签/搜索