最小生成树--Prim算法

Posted duanqibo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树--Prim算法相关的知识,希望对你有一定的参考价值。

最小生成树的概念:

       最小生成树是基于“带权图” 的,即图中每条边上都有特定的权值,这样的图又称为网。最小生成树指的是所有生成树中,权值之和最小的树。

Prim算法:

       假设G=(V,E)为一网图,其中V为顶点的集合,E为边的集合。从某一顶点u1出发,选择与它关联的具有最小权值的边(u1, v),将其顶点v加入到生成树顶点

集合U中。U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边。

令集合U的初值为U=u1 (假设构造最小生成树时,从顶点u1出发),集合T的初值为T= 。

      以后每一步从U中选择一个顶点u(u属于U),而另一个顶点v属于V-U的边中,选取具有最小权值的边(u,v),将顶点v加入集合U中,将边(u,v)加入集合T

中,如此不断重复,直到U=V时,最小生成树构造完毕,这时集合T中包含了最小生成树的所有边。

Prim算法的描述:

(1)U=u1 , T=

  (2)  while(U<>V)

        (u,v)=minWuv ; u属于U, v属于V-U;

        T=T+ (u, v) ;

        U=U + v .

 (3) 结束

 

技术图片

 

在构造过程中,设置了两个辅助数组:lowcost[]存放生成树顶点集合U内顶点到生成树外V-U各顶点的各边上的当前最小权值;

nearvex[]记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小).

若选择从顶点0出发,即u=0, 则两个辅助数组的初始状态为:

 

技术图片

反复做以下工作:

(1) 在lowcost[ ]中选择nearvec[ ]<>-1 && lowcost[i]最小的边,用v标记它。则选中的权值最小的边为(nearvex[v] , v),相应的权值为lowcost[v]。

 

 

 

技术图片

程序如下:

//

//  main.cpp

//  Prim

//

//  Created by duanqibo on 2019/7/3.

//  Copyright © 2019年 duanqibo. All rights reserved.

//  Prim普利姆算法建立最小生成树

 

#include <iostream>

#include <stdio.h>

 

#define MaxVerNum 100

#define MaxValue 10000

typedef struct

    char vexs[MaxVerNum];  //顶点集合

    int edges[MaxVerNum][MaxVerNum];  //边集合

    int n,e;  //顶点和边

MGraph;

 

char vertex[]="0123456";

int nvertex=7,nedges=9;

int connection[][3]=0,1,28,0,5,10,1,2,16,1,6,14,2,3,12,3,4,22,3,6,18,4,5,25,4,6,24;

 

void CreateMgraph(MGraph &G)

    int i,j,k;

    G.n=nvertex;

    G.e=nedges;

    for(i=0;i<G.n;i++)

        G.vexs[i]=vertex[i];  //顶点

    for(i=0;i<G.n;i++)

        for(j=0;j<G.n;j++)

            G.edges[i][j]=MaxValue; //初始化边最大值,没有边

    for(i=0;i<G.n;i++)

        G.edges[i][i]=0;  //初始化边为0

    

    for(k=0;k<G.e;k++)

   

        i=connection[k][0];

        j=connection[k][1];

        G.edges[i][j]=connection[k][2];

        G.edges[j][i]=G.edges[i][j]; //有向图没有这一行

   

 

void printMgraph(MGraph &G)

    int i,j;

    printf("图的结点总数:%d  边总数:%d\\n",G.n,G.e);

    for(i=0;i<G.n;i++)

   

        for(j=0;j<G.n;j++)

            if(G.edges[i][j]==10000)

                printf("∞   "); //"00"代表无穷

            else

                printf("%d   ",G.edges[i][j]);

        printf("\\n");

   

 

//最小生成树

typedef struct

    int head,tail,cost;

MST[MaxVerNum];

 

void Prim(MGraph &G,MST &T,int u)

    int i,j;

    int *lowcost=new int[G.n];

    int *nearvex=new int[G.n];

    for(i=0;i<G.n;i++)

   

        lowcost[i]=G.edges[u][i]; //u到各点的代价

        nearvex[i]=u;   //最短带权路径

   

    nearvex[u]=-1;  //加入到生成树顶点集合

    int k=0;

    for(i=0;i<G.n;i++)

        if(i!=u)

       

            int min=MaxValue;

            int v=u;

            for(j=0;j<G.n;j++)

                if(nearvex[j]!=-1 && lowcost[j]<min) //=-1不参选

               

                    v=j;

                    min=lowcost[j];//求生成树外顶点到生成树内顶点具有最小权值的边,

                                   //v是当前具有最小权值的边

               

            if(v!=u)

           

                T[k].tail=nearvex[v];

                T[k].head=v;

                T[k++].cost=lowcost[v];

                nearvex[v]=-1;  //该边加入生成树标记

                for(j=0;j<G.n;j++)

                    if(nearvex[j]!=-1 && G.edges[v][j]<lowcost[j])

                   

                        lowcost[j]=G.edges[v][j];  //修改

                        nearvex[j]=v;

                   

           

            

        //循环n-1次,加入n-1条边

 

 

int main(int argc, const char * argv[])

    int i;

    MGraph g;

    CreateMgraph(g);

    printMgraph(g);

    MST t;

    Prim(g,t,0);

    printf("生成树:结点->权值->结点\\n");

    for(i=0;i<g.n;i++)

        printf("(%d)-->%d-->(%d)\\n",t[i].tail,t[i].cost,t[i].head);

    return 1;

 运行结果如下: 

技术图片

 

以上是关于最小生成树--Prim算法的主要内容,如果未能解决你的问题,请参考以下文章

prim和kruscal算法得到的最小生成树是不是一样

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

最小生成树prim()算法;

最小生成树-prim算法

图的最小生成树算法?

急!数据结构最小生成树prim算法C语言实现