最小生成树算法——Kruskal算法Java实现

来源:互联网 发布:福州网络学校 编辑:程序博客网 时间:2024/05/16 01:23
闲来无事,写个算法,最小生成树的Kruskal算法,相对比Prim算法实现起来麻烦一点点
package trees;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.PriorityQueue;import java.util.Set;/** * 最小生成树的Kruskal算法, * For a connected weighted graph G, a spanning tree T of G is constructed as follows: * For the first edge e1 of T, we select any edge of G of minimum weight and for the second * edge e2 of T, we select any remaining edge of G of minimum weight. For the third edge e3 * of T,we choose any remaining edge of G of minimum weight that dose not produce a cycle with * the previousely selected edges. We continue in this manner until a spanning tree is produced. * @author xhw * */public class KruskalMinimumSpanningTree {/** * @param args */public static void main(String[] args) {double graph[][]={{0,1,4,4,5},  {1,0,3,7,5},  {4,3,0,6,Double.MAX_VALUE},  {4,7,6,0,2},  {5,5,Double.MAX_VALUE,2,0}};double tree[][]=minimumSpanningTree(graph);if(tree==null){System.out.println("no spanning tree");System.exit(0);}PriorityQueue<Edge> edgeList=generateEdgeList(tree);for(Edge e:edgeList){System.out.println(e);}}/** * 给定一个带权值的邻接矩阵(其中若i=j,权值为0,若i和j不可达权值为Double.max),返回一个最小生成树, * @param graph * @return */public static double[][] minimumSpanningTree(double[][] graph) {int rlength=graph.length;int clength=graph[0].length;PriorityQueue<Edge> edgeList;edgeList=generateEdgeList(graph);double tree[][]=new double[rlength][clength];/** * 初始化tree */for(int i=0;i<rlength;i++){for(int j=0;j<clength;j++){if(i==j)tree[i][j]=0;elsetree[i][j]=Double.MAX_VALUE;}}/** * map用于标识边的某个顶点属于哪个集合,认为顶点刚开始属于不同的集合,当选择一条边时,就合并两个集合,如果选择的边在同一个集合内,就代表有环路出现了 */Map<Integer,Set<Integer>> map=new HashMap<Integer,Set<Integer>>();int edgeCount=0;while(edgeCount<rlength-1&&!edgeList.isEmpty()){Edge e=edgeList.poll();Set<Integer> setU=map.get(e.u);Set<Integer> setV=map.get(e.v);//System.out.println(e);//边的两个顶点都未出现在其他集合中if(setU==null&&setV==null){Set<Integer> set=new HashSet<Integer>();set.add(e.u);set.add(e.v);map.put(e.u, set);map.put(e.v, set);}//有一个顶点在其他集合中,一个不在,将不在的那个顶点集合合并进去else if(setU==null&&setV!=null){map.put(e.u, setV);setV.add(e.u);}else if(setU!=null&&setV==null){map.put(e.v, setU);setU.add(e.v);}//分别在不同的集合中,合并两个集合else if(setU!=setV){for(int v:setV){map.put(v, setU);}setU.addAll(setV);}//两个顶点在同一个结合中,会出现环路,舍弃else{continue;}tree[e.u][e.v]=e.weight;tree[e.v][e.u]=e.weight;edgeCount++;}if(edgeCount==rlength-1)return tree;elsereturn null;}/** * 生成边的排序好的队列 * @param graph * @return */private static PriorityQueue<Edge> generateEdgeList(double[][] graph) {PriorityQueue<Edge> edgeList=new PriorityQueue<Edge>();int rlength=graph.length;int clength=graph[0].length;for(int i=0;i<rlength;i++){for(int j=i+1;j<clength;j++ ){if(graph[i][j]>0&graph[i][j]<Double.MAX_VALUE){Edge e=new Edge(i,j,graph[i][j]);edgeList.add(e);}}}return edgeList;}}class Edge implements Comparable<Edge>{int u;int v;double weight;public Edge(int u, int v, double weight) {super();this.u = u;this.v = v;this.weight = weight;}@Overridepublic int compareTo(Edge e) {if(e.weight==weight)return 0;else if(weight<e.weight)return -1;elsereturn 1;}public String toString(){return u+"--"+v+":"+weight;}}

原创粉丝点击