prim算法

1.prim算法概述

        普里姆算法Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。

2.prim算法详解

图例

说明

不可选

可选

已选(Vnew)

此为原始的加权连通图。每条边一侧的数字代表其权值。

-

-

-

顶点D被任意选为起始点。顶点ABEF通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。

C, G

A, B, E, F

D

下一个顶点为距离DA最近的顶点。BD为9,距A为7,E为15,F为6。因此,FDA最近,因此将顶点F与相应边DF以高亮表示。

C, G

B, E, F

A, D

算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。

C

B, E, G

A, D, F

在当前情况下,可以在CEG间进行选择。CB为8,EB为7,GF为11。点E最近,因此将顶点E与相应边BE高亮表示。

C, E, G

A, D, F, B

这里,可供选择的顶点只有CGCE为5,GE为9,故选取C,并与边EC一同高亮表示。

C, G

A, D, F, B, E

顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG

G

A, D, F, B, E, C

所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。

A, D, F, B, E, C, G

3.java代码实现

/**
 * @author wangli
 * @data 2022/6/13 14:44
 * @Description:
 */
public class PrimArithmetic {
    @Test
    public void PrimArithmeticDemo(){

        char[] vertexs = new char[] {'A','B','C','D','E','F','G'};
        Graph graph = new Graph(vertexs);
        int[][] edges = new int[][] {
                {10000,5,7,10000,10000,10000,2},
                {5,10000,10000,9,10000,10000,3},
                {7,10000,10000,10000,8,10000,10000},
                {10000,9,10000,10000,10000,4,10000},
                {10000,10000,8,10000,10000,5,4},
                {10000,10000,10000,4,5,10000,6},
                {2,3,10000,10000,4,6,10000}};
        createTree(graph,vertexs,edges);
        graph.showGraph();
        minPrim(graph,0);

    }

    /**
     * 最小生成树
     * @param graph
     * @param v 起始节点
     */
    public void minPrim(Graph graph,int v){
        //visited[] 标记结点是否被访问过
        Integer[] visiteds = new Integer[graph.vertex.length];
        for (int i = 0; i < visiteds.length; i++) {
            visiteds[i]=0;
        }
        visiteds[v]=1;
        int min=10000;
//        记录起始点
        int startVertex=-1;
//        记录终点
        int endVertex=-1;
        for (int i = 0; i < graph.vertex.length; i++) {
            for (int j = 0; j < graph.vertex.length; j++) {
                for (int k = 0; k < graph.vertex.length; k++) {
                    if (visiteds[j]==1&&visiteds[k]==0&&graph.edges[j][k]<min){
                        min=graph.edges[j][k];
                        startVertex=j;
                        endVertex=k;
                    }
                }
            }
            System.out.println("边<" + graph.vertex[startVertex] + graph.vertex[endVertex] + ">权值:" + min);
//            表示该点以及被遍历过
            visiteds[endVertex]=1;
            min=10000;
        }
    }

    /**
     * 创建树
     */
    public void createTree(Graph graph,char[] vertexes,int[][] edges){
        for (int i = 0; i < vertexes.length; i++) {
            graph.vertex[i]=vertexes[i];
            for (int j = 0; j < vertexes.length; j++) {
                graph.edges[i][j]=edges[i][j];
            }
        }
    }
    @Data
    static class Graph{
        //    节点
        private char[] vertex;
        //    邻接矩阵
        private int[][] edges;

        public Graph(char[] vertex) {
            this.vertex=vertex;
            edges=new int[vertex.length][vertex.length];

        }

        /**
         * 查看邻接矩阵
         */
        public void showGraph(){
            for (int i = 0; i < vertex.length; i++) {
                for (int j = 0; j < vertex.length; j++) {
                    System.out.printf("%15d",edges[i][j]);
                }
                System.out.println();
            }
        }

    }

}

生成的最短路径如下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨会停rain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值