最小生成树-Prim算法实现

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、测试结果
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值