普里姆算法(Prim)

57 篇文章 1 订阅
52 篇文章 2 订阅

  普里姆(Prim)算法是一种构造性算法。假设 G=(V,E) 是一个具有 n 个顶点的带权连通图,T=(U,TE) G 的最小生成树,其中U T 的顶点集,TE T 的边集,则从v0开始构造最小生成树 T 的步骤如下:
  1) 初始化={v0},将 v0 到其他顶点的所有边作为候选边。
  2) 重复以下操作 n1 次,使得其他 n1 个顶点被加入到 U 中:
  2.1) 从候选边中挑选权值最小的边输出,设该边在VU中的顶点是 v , 将v加入到 U 中,删除和v关联的边;
  2.2) 考察当前 VU 中的所有顶点 vi ,修正候选边。若 (v,vi) 的权值小于原来和 vi 关联的候选边,则用 (v,vi) 取代后者作为候选边。
  为了便于在集合 U VU之间选择权值最小的边,建立了两个数组 vset lowcost vset[i]=1 表示顶点 i U中, vset[i]=0 表示顶点 i VU中。 lowcost 数组存放 VU 顶点到 U 中顶点的最小值,即lowcost[i]表示 VU 中顶点 i U中顶点的最短边的权值。
  初始时 lowcost[i]=g.edges[v0][i] ,
  在扩充顶点 v 后,若vset[j]=1(表示为 VU 中顶点), 且 g.edges[v][j]<lowcost[j] , 说明 VU 中的顶点 j U中顶点 v 的边权值更短, 需修改为lowcost[j]=g.edges[v][j]
  普里姆算法如下:  

void prim(MGraph g,int v)
{
    int lowcost[MAXV],min,n=g.vexnum;
    int closest[MAXV],i,j,k;
    for (i=0;i<n;i++)           //给lowcost[]和closest[]置初值
    {   
        lowcost[i]=g.edges[v][i];
        closest[i]=v;
    }
    for (i=1;i<n;i++)           //找出n-1个顶点
    {   
        min=INF;
        for (j=0;j<n;j++)       //在(V-U)中找出离U最近的顶点k
            if (lowcost[j]!=0 && lowcost[j]<min) 
            {   
                min=lowcost[j];k=j;  
            }
        printf("  边(%d,%d)权为:%d\n",closest[k],k,min);
        lowcost[k]=0;           //标记k已经加入U
        for (j=0;j<n;j++)       //修改数组lowcost和closest
            if (g.edges[k][j]!=0 && g.edges[k][j]<lowcost[j]) 
            {   
                lowcost[j]=g.edges[k][j];closest[j]=k; 
            }
    }
}

  普里姆算法的时间复杂度为 O(n2) ,适用于稠密图。

普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法都是用于解决最小生成树问题的算法最小生成树问题是指在一个无向连通中,找到一棵生成树,使得树上所有边的权值之和最小。生成树是指一个无向的生成子,它是一棵树,且包含中所有顶点。 下面我们分别介绍普里姆算法和克鲁斯卡尔算法: 1. 普里姆算法 普里姆算法是一种贪心算法,它从一个任意点开始,逐步扩展生成树,每次选择当前生成树到未加入的点中距离最近的点,并将其加入生成树。 具体实现步骤如下: - 随机选择一个起始点,将其加入生成树。 - 在生成树中的所有节点中,找到到未加入生成树的节点中距离最小的节点,将其加入生成树。 - 重复以上步骤,直到生成树包含了所有节点。 2. 克鲁斯卡尔算法 克鲁斯卡尔算法也是一种贪心算法,它从边集合中选择边,逐步扩展生成树,每次选择当前边集合中权值最小的边,并将其加入生成树。 具体实现步骤如下: - 将所有边按照权值从小到大排序。 - 从权值最小的边开始,逐个加入生成树,如果加入当前边会形成环,则不加入该边。 - 重复以上步骤,直到生成树包含了所有节点。 两种算法时间复杂度都是O(ElogE),其中E为边数。普里姆算法在处理稠密时效率更高,而克鲁斯卡尔算法在处理稀疏时效率更高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

sanqima

一键三连,多多益善

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

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

打赏作者

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

抵扣说明:

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

余额充值