最小生成树算法(Prim和Kruskal算法)

在一个连通网图中,构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning Tree)。

普里姆(Prim)算法

步骤:
  • 生成树的点集为U,边集为Te,设初始点集合为图中任意一点u~0~,Te为空;
  • 在所有u∈U、v∈V-U的边(u,v)中找一条权值最小的边并入集合Te,同时该点并入集合U中;
  • 对每个点重复以上操作,直到U=V,此时Te即为最小生成树。

Prim算法代码示例(图以邻接矩阵表示):

    //构建最小生成树,matrix为无向网图邻接矩阵
    private static void MiniSpanTree_Prim(){
        int min,i,j,k;

        int[] adjvex = new int[MAXVEX];

        int[] lowcost = new int[MAXVEX];

        lowcost[0] = 0;

        adjvex[0] = 0;

        for(i = 1; i < matrix.getVerNum(); i++){
            lowcost[i] = matrix.getArc()[0][i];
            adjvex[i] = 0;
        }

        for (i = 1; i < matrix.getVerNum(); i++){
            min = INFINITY;

            j = 1;
            k = 0;

            while (j < matrix.getVerNum()){
                if(lowcost[j] != 0 && lowcost[j] < min){
                    min = lowcost[j];
                    k = j;
                }

                j++;;
            }

            System.out.print(adjvex[k]+", "+k + " -> ");
            lowcost[k] = 0;

            for (j = 1; j < matrix.getVerNum(); j++){
                if(lowcost[j] != 0 && matrix.getArc()[k][j] < lowcost[j]){
                    lowcost[j] = matrix.getArc()[k][j];
                    adjvex[j] = k;
                }
            }
        }
    }

Prim算法时间复杂度为O(n^2^)

克鲁斯卡尔(Kruskal)算法

步骤:
  • 将边集数组按权值从大小到大排序;
  • 依次找出权值最小的边,若不出现环路,就将其加入最小生成树。

实现代码如下:

    //构造最小生成树
    private static void MiniSpanTree_Kruskal(){
        Edge[] edges = new Edge[matrix.getEdgeNum()];

        int i,n,m;
        int l = 0;

        int[] parent = new int[MAXVEX];   //判断是否发生回路

        for(i = 0; i < matrix.getVerNum(); i++){
            for(int j = i; j < matrix.getVerNum(); j++){
                if(matrix.getArc()[i][j] > 0 && matrix.getArc()[i][j] < INFINITY){
                    edges[l] = new Edge(i,j,matrix.getArc()[i][j]);
                    l++;
                }
            }
        }
        Arrays.sort(edges, Comparator.comparingInt(o -> o.weight));

        for (i = 0; i < matrix.getVerNum(); i++){
            parent[i] = 0;
        }

        for (i = 0; i < matrix.getEdgeNum(); i++){
            n = Find(parent, edges[i].start);
            m = Find(parent,edges[i].end);
            if(n != m){
                parent[n] = m;
                System.out.print(edges[i].start+", "+edges[i].end+", "+edges[i].weight+" -> ");
            }
        }
    }

    //查找连线顶点的尾部下标
    private static int Find(int[] parent, int f){
        while (parent[f] > 0)
            f = parent[f];
        return f;
    }

Find函数时间复杂度为O(lge),循环e次,时间复杂度为O(elge)。

本文用到的代码链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值