最小生成树-Prim算法实现

来源:互联网 发布:淘宝html源代码 编辑:程序博客网 时间:2024/06/14 16:33

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>();        // 当“取得的边数==顶点数-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、测试结果
这里写图片描述

原创粉丝点击