java克鲁斯卡尔(kruskal)最小生成树代码实现

import java.util.Arrays;

/**
 * @author Drug
 * @create 2020-05-16 12:01
 */
public class Kurskal {
    //边数
    private int edgeNum;
    //顶点信息
    private char[] vertexs;
    //权值矩阵
    private int[][] matrix;
    //表示无法连通的最大值
    private static final int INF = Integer.MAX_VALUE;


    public static void main(String[] args) {
        char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        //克鲁斯卡尔算法的邻接矩阵
        int[][] matrix = {
                /*A*//*B*//*C*//*D*//*E*//*F*//*G*/
                /*A*/ {0, 12, INF, INF, INF, 16, 14},
                /*B*/ {12, 0, 10, INF, INF, 7, INF},
                /*C*/ {INF, 10, 0, 3, 5, 6, INF},
                /*D*/ {INF, INF, 3, 0, 4, INF, INF},
                /*E*/ {INF, INF, 5, 4, 0, 2, 8},
                /*F*/ {16, 7, 6, INF, 2, 0, 9},
                /*G*/ {14, INF, INF, INF, 8, 9, 0}};
        //大家可以在去测试其它的邻接矩阵,结果都可以得到最小生成树.

        //Kurskal 对象实例
        Kurskal kurskal = new Kurskal(vertexs, matrix);
        //输出构建的
        kurskal.print();
        EData[] eData = kurskal.getEData();
        System.out.println(Arrays.toString(eData));
        System.out.println("克鲁斯卡尔法求最小生成树后:");;
        kurskal.kruskal();
    }

    /**
     * 构造
     *
     * @param nVertexs
     * @param nMatrix
     */
    public Kurskal(char[] nVertexs, int[][] nMatrix) {
        vertexs = new char[nVertexs.length];
        //顶点信息赋值
        for (int i = 0; i < nVertexs.length; i++) {
            vertexs[i] = nVertexs[i];
        }
        //边信息赋值
        matrix = new int[nMatrix.length][nMatrix[0].length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                matrix[i][j] = nMatrix[i][j];
                if (matrix[i][j] != INF && i > j) {
                    edgeNum++;
                }
            }
        }
    }

    /**
     * 打印输出
     */
    public void print() {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                System.out.printf("%12d", matrix[i][j]);
            }
            System.out.println();
        }
    }

    /**
     * 按照边权值排序
     *
     * @param edges
     */
    private void sortEdges(EData[] edges) {
        for (int i = 0; i < edges.length - 1; i++) {
            for (int j = 0; j < edges.length - 1 - i; j++) {
                if (edges[j].weight > edges[j + 1].weight) {
                    EData temp = edges[j];
                    edges[j] = edges[j + 1];
                    edges[j + 1] = temp;
                }
            }
        }
    }

    /**
     * 返回顶点下标
     *
     * @param c
     * @return
     */
    private int getPosition(char c) {
        for (int i = 0; i < vertexs.length; i++) {
            if (vertexs[i] == c) {
                return i;
            }
        }
        //没有找到
        return -1;
    }

    /**
     * 返回边信息
     * @return
     */
    private EData[] getEData() {
        //计算器
        int index = 0;
        //初始化
        EData[] edges = new EData[edgeNum];
        //赋值
        for(int i=0;i<matrix.length;i++){
            for(int j=i+1;j<matrix[0].length;j++){
                if(matrix[i][j] != INF){
                    edges[index++] = new EData(vertexs[i],vertexs[j],matrix[i][j]);
                }
            }
        }
        return edges;
    }

    /**
     * 返回顶点i对应的终点信息
     * @param ends
     * @param i
     * @return
     */
    private int getEnd(int[] ends, int i) {
        //如果end[i]等于0,说明没有指向,即返回本身
        //如果不等于0,说明有指向,返回指向节点
        while(ends[i] != 0) {
            i = ends[i];
        }
        return i;
    }

    private void kruskal(){
        //计数器
        int index = 0;
        //各边的终点
        int[] end = new int[edgeNum];
        //结果集,n个顶点 n-1条边
        EData[] res = new EData[vertexs.length-1];
        //获得边信息
        EData[] edges = getEData();
        //排序边信息
        sortEdges(edges);
        //开始依次判断
        for(int i=0;i<edgeNum;i++){
            //一个顶点
            int p1 = getPosition(edges[i].start);
            //另一个顶点
            int p2 = getPosition(edges[i].end);
            //获得p1终点信息
            int end1 = getEnd(end, p1);
            //获得p2终点信息
            int end2 = getEnd(end, p2);
            //如果两点不构成回路
            if(end1 != end2){
                //终点信息变更
                end[end1] = end2;
                //结果加入数组
                res[index++] = edges[i];
            }
        }
        System.out.println(Arrays.toString(res));
    }
}

class EData {
    /**
     * 一个端点
     */
    char start;
    /**
     * 另一个端点
     */
    char end;
    /**
     * 权值
     */
    int weight;

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

    @Override
    public String toString() {
        return "EData{" +
                "<" + start +
                ", " + end +
                "> " + weight +
                '}';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值