最小生成树算法-Prim算法

MST(Minimum Spanning Tree,最小生成树)问题有两种通用的解法,Prim算法就是其中之一,它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。

package com.gloomy.graph;

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

/**
 * 最小生成树算法
 * 与Dijkstra算法思路几乎完全一致
 * 
 * @author 过路的守望
 *
 */
public class PrimAlgorithm {

    public static void main(String[] args) {

        Vertex A = new Vertex("A");
        Vertex B = new Vertex("B");
        Vertex C = new Vertex("C");
        Vertex D = new Vertex("D");
        Vertex E = new Vertex("E");
        Vertex F = new Vertex("F");
        Vertex G = new Vertex("G");
        A.getAdjacentList().add(B);
        A.getAdjacentList().add(D);
        A.getAdjacentList().add(C);
        A.getAdjacentEdgesMap().put(B, 2);
        A.getAdjacentEdgesMap().put(C, 4);
        A.getAdjacentEdgesMap().put(D, 1);
        B.getAdjacentList().add(E);
        B.getAdjacentList().add(D);
        B.getAdjacentList().add(A);
        B.getAdjacentEdgesMap().put(A, 2);
        B.getAdjacentEdgesMap().put(D, 3);
        B.getAdjacentEdgesMap().put(E, 10);
        C.getAdjacentList().add(A);
        C.getAdjacentList().add(D);
        C.getAdjacentList().add(F);
        C.getAdjacentEdgesMap().put(A, 4);
        C.getAdjacentEdgesMap().put(D, 2);
        C.getAdjacentEdgesMap().put(F, 5);
        D.getAdjacentList().add(A);
        D.getAdjacentList().add(B);
        D.getAdjacentList().add(C);
        D.getAdjacentList().add(E);
        D.getAdjacentList().add(F);
        D.getAdjacentList().add(G);
        D.getAdjacentEdgesMap().put(A, 1);
        D.getAdjacentEdgesMap().put(B, 3);
        D.getAdjacentEdgesMap().put(C, 2);
        D.getAdjacentEdgesMap().put(E, 7);
        D.getAdjacentEdgesMap().put(F, 8);
        D.getAdjacentEdgesMap().put(G, 4);
        E.getAdjacentList().add(B);
        E.getAdjacentList().add(D);
        E.getAdjacentList().add(G);
        E.getAdjacentEdgesMap().put(B, 10);
        E.getAdjacentEdgesMap().put(D, 7);
        E.getAdjacentEdgesMap().put(G, 6);
        F.getAdjacentList().add(C);
        F.getAdjacentList().add(D);
        F.getAdjacentList().add(G);
        F.getAdjacentEdgesMap().put(C, 5);
        F.getAdjacentEdgesMap().put(D, 8);
        F.getAdjacentEdgesMap().put(G, 1);
        G.getAdjacentList().add(F);
        G.getAdjacentList().add(D);
        G.getAdjacentList().add(E);
        G.getAdjacentEdgesMap().put(F, 1);
        G.getAdjacentEdgesMap().put(E, 6);
        G.getAdjacentEdgesMap().put(D, 4);
        List<Vertex> vertexs = new ArrayList<Vertex>();
        vertexs.add(A);
        vertexs.add(B);
        vertexs.add(C);
        vertexs.add(D);
        vertexs.add(E);
        vertexs.add(F);
        vertexs.add(G);
        PrimAlgorithm prim = new PrimAlgorithm();
        prim.primTree(A, vertexs);
    }

    /**
     * 
     * @param vertex
     *            指定的根
     * @param vertexs
     *            顶点的集合
     */
    public void primTree(Vertex vertex, List<Vertex> vertexs) {
        Vertex curVertex = vertex;
        vertex.setDist(0);
        while (true) {
            /*
             * 已经处理完所有顶点
             */
            if (curVertex == null) {
                break;
            }
            curVertex.setVisited(true);
            for (Vertex adjaVertex : curVertex.getAdjacentList()) {
                /*
                 * 若adjacent顶点未处理
                 * 且d[w]=min(d[w],C(w,v))变小
                 * 更新此顶点
                 */
                if (!adjaVertex.isVisited()) {
                    if (adjaVertex.getDist() > curVertex.getAdjacentEdgesMap()
                            .get(adjaVertex)) {
                        adjaVertex.setDist(curVertex.getAdjacentEdgesMap().get(
                                adjaVertex));
                        adjaVertex.setPreVertex(curVertex);
                    }
                }

            }
            /*
             * 从未访问顶点中寻找下一个顶点
             */
            curVertex = getShortestVertex(vertexs);

        }
        int length = 0;
        for (Vertex vertex2 : vertexs) {
            length += vertex2.getDist();
        }
        System.out.println("权值和:"+length);
    }

    /**
     * 从未访问顶点中寻找最短边
     * 可用二叉堆优化
     * @param vertexs
     * @return
     */
    public Vertex getShortestVertex(List<Vertex> vertexs) {
        int min = Integer.MAX_VALUE;
        /*
         * 最短边
         */
        Vertex minVertex = null;
        for (Vertex vertex : vertexs) {
            if (!vertex.isVisited()) {
                if (vertex.getDist() < min) {
                    min = vertex.getDist();
                    minVertex = vertex;
                }
            }
        }
        return minVertex;
    }

}

权值和:16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值