/** * 文件名: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])); } }