您的位置:首页 > 其它

最小生成树-Prim算法实现

2017-08-16 14:29 337 查看
1、建立结点类

//结点

public class Node {
private String data;
private boolean isVisited;

public Node(String data) {
this.data = data;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}

public boolean isVisited() {
return isVisited;
}

public void setVisited(boolean isVisited) {
this.isVisited = isVisited;
}

}


2、用来存储顶点之间有无边、及权值大小的边类

//边

public class Edge {
private int start;
private int end;
private int weight;
private boolean isSelected; // 是否已被选中

public Edge(int start, int end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}

public int getStart() {
return start;
}

public void setStart(int start) {
this.start = start;
}

public int getEnd() {
return end;
}

public void setEnd(int end) {
this.end = end;
}

public int getWeight() {
return weight;
}

public void setWeight(int weight) {
this.weight = weight;
}

public boolean isSelected() {
return isSelected;
}

public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}

}


3、数据源

//数据源

public class GraphData {

// 邻接矩阵
public int[][] getMatrix() {

// 非0代表权值,0代表无边
int[][] matrix = { { 0, 6, 0, 0, 5, 1 }, { 6, 0, 3, 0, 0, 2 }, { 0, 3, 0, 7, 0, 8 }, { 0, 0, 7, 0, 2, 4 },
{ 5, 0, 0, 2, 0, 9 }, { 1, 2, 8, 4, 9, 0 } };

return matrix;
}

// 顶点标签
public String[] getNodeData() {
String[] nodeData = { "A", "B", "C", "D", "E", "F" };
return nodeData;
}
}


4、Prim算法

//最小生成树之Prim算法实现

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class Prim {

// 顶点列表
private List<Node> list = new ArrayList<Node>();

GraphData gd = new GraphData();

public Prim() {

// 顶点数据
String[] nodeData = gd.getNodeData();

for (String data : nodeData) {
list.add(new Node(data));
}

getMinTree(0);
}

private void getMinTree(int nodeIndex) {

// 邻接矩阵
int[][] matrix = gd.getMatrix();

// 顶点个数
int n = matrix.length;

// 存储已确定的边的数组
Edge[] treeEdges = new Edge[n - 1];

// 存放已确定的点的索引的集合
Vector<Integer> nodeVec = new Vector<Integer>();

// 把已确定的点所连接的所有边放进一个集合,即备选边的集合
Vector<Edge> edgeVec = new Vector<Edge&g
4000
t;();

// 当“取得的边数==顶点数-1”时,可停止算法
// 计算边的数量
int edgeCount = 0;

// 总路径长度
int sum = 0;

// 将第一个点放进点的集合中
nodeVec.add(nodeIndex);

// 设置该点也被访问
list.get(nodeIndex).setVisited(true);

// 打印传进来的点
System.out.println("第" + nodeVec.size() + "个确定的点:" + list.get(nodeIndex).getData());

// 1、找到算法的结束条件
while (edgeCount < n - 1) {

// 取出传进来的顶点的索引
int temp = nodeVec.get(nodeIndex);

/**
* 寻找与该顶点连接的所有边 for循环一结束,表示已将该顶点连接的所有边放入到备选表集合中了
*/
for (int i = 0; i < n; i++) {
// 有边
if (matrix[temp][i] != 0) {
// 顶点已被访问过
if (list.get(i).isVisited()) {
continue;
} else {
// 顶点还没被访问过,那么这条边应放入备选边的集合中
edgeVec.add(new Edge(temp, i, matrix[temp][i]));
}
}
}

/**
* 从备选边集合中找到最小的边 把最小边连着的未确定的顶点放入到已确定的点的集合中
*/
// 取得最小边的在备选边集合中索引
int minEdge = getMinEdge(edgeVec);

// 设置边为已被访问状态
edgeVec.get(minEdge).setSelected(true);

// 将边放入到已确定的边的数组中
treeEdges[edgeCount] = edgeVec.get(minEdge);

// 路径长度
sum += edgeVec.get(minEdge).getWeight();

// 边数加1
edgeCount++;

// 找到与当前最小边所连接的那个点,edgeVec.get(minEdge).getStart()是当前这个点
int curNodeIndex = edgeVec.get(minEdge).getStart();
int nextNodeIndex = edgeVec.get(minEdge).getEnd();

// 将点放入到已确定的点的集合中
nodeVec.add(nextNodeIndex);

// 设置该点为已被访问状态
list.get(nextNodeIndex).setVisited(true);

// 打印顶点和边的信息
System.out.println("第" + edgeCount + "条确定的边:" + list.get(curNodeIndex).getData() + "-->"
+ list.get(nextNodeIndex).getData() + ":" + matrix[curNodeIndex][nextNodeIndex]);

// 打印下一次要循环的点
System.out.println("第" + nodeVec.size() + "个确定的点:" + list.get(nextNodeIndex).getData());

nodeIndex++;

}
System.out.println("路径长度为:" + sum);
}

private int getMinEdge(Vector<Edge> edgeVec) {

int max = Integer.MAX_VALUE;

// 最小权值
int minWeight = max;
// 最小边的索引
int edgeIndex = 0;

// 找出第一条没有被访问过的边
for (int i = 0; i < edgeVec.size(); i++) {
// 边未被访问过
if (!edgeVec.get(i).isSelected() && edgeVec.get(i).getWeight() < minWeight) {
// 将边的权值赋给minWeight
minWeight = edgeVec.get(i).getWeight();
// 最小边的索引为i
edgeIndex = i;
} else if (edgeVec.get(i).isSelected()) {
continue;
}
}

// 所有的边都已被选中,找最小边失败
if (minWeight == max)
return -1;

return edgeIndex;

}

}


5、测试

public class Test {

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

}


6、测试结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: