最小生成树之prim算法java代码

来源:互联网 发布:易族智汇 b2b2c 源码 编辑:程序博客网 时间:2024/06/05 18:23

 思路:1.初始化带权值的图,把相应的点存到一个队列V中.

    2.再创建一个用于储存最小生成树结点的队列U,
            然后先从起始结点V中取一个放进最小生成树结点U中.

       3.通过遍历U中结点来选择这些边加入到优先考虑的边

    集合中,不构成圈且权值最小的边添加到最小生成树中,且把相应     边的另一端加入到U中.

      4. 直到完成最小生成图.

Edge类:

/** * 带权重的边的数据类型 * @interface  * @author sanjun * @Time 2017-05-02 */public class Edge implements Comparable<Edge>{ private String begin; //顶点之一 private String end;   //另一个顶点 private double weight; //边的权重      public Edge(String begin, String end, double weight) {    this.begin = begin;this.end = end;this.weight = weight;   }public String getBegin() {return begin;}public void setBegin(String begin) {this.begin = begin;}public String getEnd() {return end;}public void setEnd(String end) {this.end = end;}public double getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}public void show(){System.out.println(this.getWeight());}/** * 将边进行比较后通过Arrays.sort(Object[] args0)排列 * @author sanjun * @param that */public int compareTo(Edge that){if(this.getWeight() < that.getWeight()) return -1;else if(this.getWeight() > that.getWeight()) return +1;else return 0;}}

PrimMST类:

import java.util.ArrayList;/** *   @author sanjun *   @Time 2017-5-2 */public class PrimMST {private int vertexNum; //结点数目private ArrayList<String> U = new ArrayList<String>(); //最小生成树结点private ArrayList<Edge> TE = new ArrayList<Edge>(); //最小生成树边private ArrayList<String> V = new ArrayList<String>(); //初始结点private ArrayList<Edge> E = new ArrayList<Edge>(); //初始边/** * 初始化图 * @author sanjun * @return  */private void initGraph(){vertexNum = 8; //初始化结点数for(int i = 0;i < vertexNum ;i++){ //将结点名称放进队列V中V.add(i+"");}Edge[] e = {new Edge("4","5",0.35),new Edge("4","7",0.37),new Edge("5","7",0.28),new Edge("0","7",0.16),new Edge("1","5",0.32),new Edge("0","4",0.38),new Edge("2","3",0.17),new Edge("1","7",0.19),new Edge("0","2",0.26),new Edge("1","2",0.36),new Edge("1","3",0.29),new Edge("2","7",0.34),new Edge("6","2",0.40),new Edge("3","6",0.52),new Edge("6","0",0.58),new Edge("6","4",0.93)}; //带权值的边//把边存储入Efor(int i = 0;i < e.length;i++){E.add(e[i]);}}/** * 首先,创建一个ArrayList用于存放优先考虑的边, *  然后先从起始结点V中取一个放进最小生成树结点U中, *  通过遍历U中结点来选择不构成圈且权值最小的边, *  直到完成最小生成图. *   *@return  */private void createMST() {ArrayList<Edge> priorEdges = new ArrayList<Edge>(); //优先边集合U.add(V.get(0)); //取一个结点for(int i = 0;i < U.size();i++){ //遍历最小生成树结点String v = U.get(i); //选中结点//选取与v相关联的边,加入优先边集合for(int j = 0;j < E.size();j++){Edge e = E.get(j); //选中的边//如果边e的端点存在v,即进入下一个条件if(e.getBegin().equals(v)||e.getEnd().equals(v)){//如果TE中不存在e且e不构成圈,即把e添加到priorEdges中if(!TE.contains(e)&&!isCircle(e)){priorEdges.add(e); //把相关边添加到priorEdges}}}/** *删除两端结点都存在U中的边 *原因是:上边条件所限制的边可能在下一个添加相应的 *结点到U中,导致原本存在priorEdges中的边失效(形成圈),故删除  */for(int j = 0;j < priorEdges.size();j++){if(isCircle(priorEdges.get(j))){ //如果形成圈,即删除该边priorEdges.remove(j);        }}//对priorEdge里面的边选最小权值的边//边按权值从小到大排int minIndex = 0; //最小下标Edge minEdge = priorEdges.get(minIndex);for(int j = 1;j < priorEdges.size();j++){//如果priorEdges.get(j)比minEdge小if(priorEdges.get(j).compareTo(minEdge) < 0){minIndex = j;minEdge = priorEdges.get(j);}}//在priorEdges中取权值最小的边Edge edge = priorEdges.get(minIndex);TE.add(edge);//把edge添加到TE中//由于该边的一端必定在U中,所以把其中一端加入U中if(U.contains(edge.getBegin())){U.add(edge.getEnd());}else{U.add(edge.getBegin());}priorEdges.remove(minIndex); //从中删除该边if(TE.size() == vertexNum - 1){break;}}//输出最小生成树double sum = 0;for(int i = 0;i < TE.size();i++){Edge edge = TE.get(i);sum += edge.getWeight();System.out.println(edge.getBegin()+"->"+edge.getEnd()+" 权值:"+edge.getWeight());}System.out.println("总权值:"+sum);}//判断是否成圈private boolean isCircle(Edge edge) {if(U.contains(edge.getBegin())&&U.contains(edge.getEnd())){return true;}else{return false;}}public static void main(String[]args){PrimMST primMST = new PrimMST();primMST.initGraph();primMST.createMST();}}


1 0
原创粉丝点击