思路: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)}; //带权值的边
//把边存储入E
for(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();
}
}