zoukankan      html  css  js  c++  java
  • 最小生成树--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)=min{Wuv ; 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 ",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(" ");

        }

    }

    //最小生成树

    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("生成树:结点->权值->结点 ");

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

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

        return 1;

    }

     运行结果如下: 

  • 相关阅读:
    知识点:定义input type=file 样式的方法(转)
    笔记:认识 head 标签 待 更新中……
    检讨:关于上班迟到那么‘ 一两分钟 ’的事儿
    js--局部变量
    数十万互联网从业者的共同关注!
    js--javascript中字符串常用操作总结、JS字符串操作大全
    JavaScript中浏览器兼容问题
    js--性能优化(转)
    js-知识点
    让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法--(转)
  • 原文地址:https://www.cnblogs.com/duanqibo/p/11145467.html
Copyright © 2011-2022 走看看