您的位置:首页 > 编程语言 > Java开发

Java解决算法-最小生成树-克里斯卡尔算法

2010-11-28 12:07 357 查看
import java.util.*;

/**
* 克鲁斯卡尔算法构造最小生成树,使用面向对象思路
*/

public class Task8_25_K {
private int[][] table;
private HashSet<Integer> V;// 存放卡鲁斯卡尔算法中已经涉及到的顶点名称
private ArrayList<Edge> resultEdges;
private ArrayList<Edge> initEdges;
/** 构造函数 */
public Task8_25_K() {
V = new HashSet<Integer>();
resultEdges = new ArrayList<Edge>();
initEdges = new ArrayList<Edge>();
recordGraphic();
createEdges();
KRUSKAL();
// sortInitEdges(initEdges);
System.out.println("最小生成树由下列边组成:");
System.out.println("顶点 权值 顶点");
printEdge(resultEdges);
printtable();
}
/** 克鲁斯卡尔算法 */
public void KRUSKAL() {
int timer = 1;
sortInitEdges(initEdges);
//这个while完毕之后还差最后一条边
while (timer<=5){// 最小生成树的边数等于顶点数-1
Edge curEdge = initEdges.get(0);
//判断是否构成环
if(V.contains(curEdge.getLeftV()) && V.contains(curEdge.getRightV())){//构成环
initEdges.remove(0);
timer++;
}
else{//不构成环
resultEdges.add(curEdge);
V.add(curEdge.getLeftV());
V.add(curEdge.getRightV());
initEdges.remove(0);
timer++;
}
}
resultEdges.add(findTheLastEdgeInVfromResultEdges());//自动找出最后一个边
// resultEdges.add(initEdges.get(1));//手动加上去的,在外加最后一个边,这个地方似乎不是很妥
}
/** 找到最后一个边,这个边跨越两个连通子树 */
public Edge findTheLastEdgeInVfromResultEdges(){
//此时resultEdges里面存放子树1和子树2的所有边
ArrayList<Integer> setA = new ArrayList<Integer>();//存放子树1的顶点
ArrayList<Integer> setB = new ArrayList<Integer>();//存放子树2的顶点
ArrayList<Edge> tempEdges = new ArrayList<Edge>();//临时在两子树间构架边

setA.add(resultEdges.get(0).getLeftV());//子树1初始化
setA.add(resultEdges.get(0).getRightV());//子树1初始化
for(int i=1;i<resultEdges.size();i++){//遍历前面棵子树的所有边
Edge edge = resultEdges.get(i);//获得当前遍历的边的引用
if(setA.contains(edge.getLeftV()) || setA.contains(edge.getRightV())){
setA.add(resultEdges.get(i).getLeftV());//如果当前边的两顶点有任何一个存在于setA
setA.add(resultEdges.get(i).getRightV());//即将两顶点放入setA
}
else{
setB.add(resultEdges.get(i).getLeftV());//否则放入到setB
setB.add(resultEdges.get(i).getRightV());
}
}
for(int i=0;i<setA.size();i++)//按照table建临时的边(这些边跨越setA setB)
for(int j=0;j<setB.size();j++)
if(table[setA.get(i)][setB.get(j)] > 0)
tempEdges.add(new Edge(setA.get(i),table[setA.get(i)][setB.get(j)],setB.get(j)));
Collections.sort(tempEdges);//根据权值非递减排序
return tempEdges.get(0);//返回全职最小的边的引用
}

/** 打印边的集合 */
public void printEdge(ArrayList<Edge> edges){
Iterator <Edge> it = edges.iterator();
while(it.hasNext()){
Edge edge = it.next();
System.out.println(edge);
}
}
/** 对边根据权值非递减排序 */
public void sortInitEdges(ArrayList<Edge> edges) {
Collections.sort(edges);
}

/** 创建所有边 */
public void createEdges() {
for (int i = 1; i < table.length; i++) {
for (int j = i; j < table[i].length; j++)
if (table[i][j] > 0)
initEdges.add(new Edge(i, table[i][j], j));
}
}

/** 记录图信息 */
public void recordGraphic() {

table = new int[][] { { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 6, 2, 0, 0 },
{ 0, 0, 0, 7, 2, 0, 0 }, { 0, 0, 0, 0, 9, 4, 3 },
{ 0, 0, 0, 0, 0, 7, 6 }, { 0, 0, 0, 0, 0, 0, 3 },
{ 0, 0, 0, 0, 0, 0, 0 } };
for (int i = 1; i < table.length; i++)
for (int j = i + 1; j < table.length; j++)
table[j][i] = table[i][j];
}

/** 打印图信息 */
public void printtable() {
System.out.println("");
System.out.println("图的信息:");
for (int i = 1; i < table.length; i++) {
for (int j = 1; j < table.length; j++) {
System.out.printf("%3d", table[i][j]);
}
System.out.print("/n");
}
}

public static void main(String[] args) {
new Task8_25_K();
}
}

class Edge implements Comparable<Object> {//边类 实现comparable接口方便排序
private int length;// 边的长度
private int leftV;// 边的一个顶点的名字
private int rightV;// 边的另一个定点的名字

public int getLength() {
return length;
}

public void setLength(int length) {
this.length = length;
}

public int getLeftV() {
return leftV;
}

public void setLeftV(int leftV) {
this.leftV = leftV;
}

public int getRightV() {
return rightV;
}

public void setRightV(int rightV) {
this.rightV = rightV;
}

public Edge(int leftV, int length, int rightV) {
this.leftV = leftV;
this.length = length;
this.rightV = rightV;
}

public Edge() {

}

@Override
public int compareTo(Object e) {
if (((Edge) e).length > this.length)
return -1;
else if (((Edge) e).length == this.length)
return 0;
else
return 1;
}

public String toString(){
return (this.leftV+"<----"+this.length+"---->"+this.rightV);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: