当前位置:首页 » 操作系统 » 最小生成树算法prim

最小生成树算法prim

发布时间: 2022-08-24 15:27:02

1. 什么是Prim算法

Prim算法
Prim算法用于求无向图的最小生成树

设图G =(V,E),其生成树的顶点集合为U。
①、把v0放入U。
②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。
③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。
其算法的时间复杂度为O(n^2)

Prim算法实现:
(1)集合:设置一个数组set[i](i=0,1,..,n-1),初始值为 0,代表对应顶点不在集合中(注意:顶点号与下标号差1)
(2)图用邻接阵表示,路径不通用无穷大表示,在计算机中可用一个大整数代替。

参考程序

/* Prim.c

Copyright (c) 2002, 2006 by ctu_85

All Rights Reserved.

*/

/* The impact of the situation of articulation point exists can be omitted in Prim algorithm but not in Kruskal algorithm */

#include "stdio.h"

#define maxver 10

#define maxright 100

int main()

{

int G[maxver][maxver],in[maxver]=,path[maxver][2];

int i,j,k,min=maxright;

int v1,v2,num,temp,status=0,start=0;

restart:

printf("Please enter the number of vertex(s) in the graph:\n");

scanf("%d",&num);

if(num>maxver||num<0)

{

printf("Error!Please reinput!\n");

goto restart;

}

for(j=0;j<num;j++)

for(k=0;k<num;k++)

{

if(j==k)

G[j][k]=maxright;

else

if(j<k)

{

re:

printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);

scanf("%d",&temp);

if(temp>=maxright||temp<-1)

{

printf("Invalid input!\n");

goto re;

}

if(temp==-1)

temp=maxright;

G[j][k]=G[k][j]=temp;

}

}

for(j=0;j<num;j++)

{

status=0;

for(k=0;k<num;k++)

if(G[j][k]<maxright)

{

status=1;

break;

}

if(status==0)

break;

}

do

{

printf("Please enter the vertex where Prim algorithm starts:");

scanf("%d",&start);

}while(start<0||start>num);

in[start-1]=1;

for(i=0;i<num-1&&status;i++)

{

for(j=0;j<num;j++)

for(k=0;k<num;k++)

if(G[j][k]<min&&in[j]&&(!in[k]))

{

v1=j;

v2=k;

min=G[j][k];

}

if(!in[v2])

{

path[i][0]=v1;

path[i][1]=v2;

in[v1]=1;

in[v2]=1;

min=maxright;

}

}

if(!status)

printf("We cannot deal with it because the graph is not connected!\n");

else

{

for(i=0;i<num-1;i++)

printf("Path %d:vertex %d to vertex %d\n",i+1,path[i][0]+1,path[i][1]+1);

}

return 1;

}

Prim算法。

设图G =(V,E),其生成树的顶点集合为U。

①、把v0放入U。

②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。

③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。

其算法的时间复杂度为O(n^2)

参考程序

//Prim 算法 读入顶点数(n)、边数(m),边的起始点和权值 用邻接矩阵储存

//例如

//7 12 (7个顶点12条边)

//1 2 2

//1 4 1

//1 3 4

//2 4 3

//2 5 10

//3 4 2

//4 5 7

//3 6 5

//4 6 8

//4 7 4

//5 7 6

//6 7 1

#include <stdio.h>

#include <string.h>

int main()

{

int m , n;

int a[201][201] , mark[201] , pre[201] , dist[201];

int s , t , w;

int i , j , k , min , tot;

freopen("Prim.txt" , "r" , stdin);

//读入数据

memset(a , 0 , sizeof(a));

scanf("%d %d" , &n , &m);

for (i = 0; i < m; i ++)

{

scanf("%d %d %d" , &s , &t , &w);

a[s][t] = w; a[t][s] = w;

}

//赋初值

memset(mark , 0 , sizeof(mark));

memset(pre , 0 , sizeof(pre));

memset(dist , 9999 , sizeof(dist));

dist[1] = 0;

//Prim

for (i = 1; i <= n; i ++)

{

min = 9999; k = 0;

for (j = 1; j <= n; j ++)

if ((mark[j] == 0) && (dist[j] < min)) {min = dist[j]; k = j;}

if (k == 0) break;

mark[k] = 1;

for (j = 1; j <= n; j ++)

if ((mark[j] == 0) && (a[k][j] < dist[j]) && (a[k][j] > 0))

{

dist[j] = a[k][j];

pre[j] = k;

}

}

tot = 0;

for (i = 1; i <= n; i ++) tot += dist[i];

printf("%d\n" , tot);

return 0;

}

2. Prim算法 最小生成树问题

你的图里有两条边权重一样,在实际计算前无法事先保证最小生成树的唯一性,即使是两个不同的Prim算法也可能产生不同的结果
当然,计算完之后情况会略有不同,下面会解释

Prim算法首先会依次选
E(1,2)=1
E(2,7)=2
E(2,3)=3
然后E(3,4)=E(7,6)=4,会面临两种选择
如果优先选E(3,4)这条边,那么下一步仍然会选E(7,6),反过来也一样,所以这个图恰好没影响
继续下去最终得到
E(1,2)=1
E(2,7)=2
E(2,3)=3
E(3,4)=4
E(7,6)=4
E(4,5)=6
这样6条边构成唯一的最小生成树,总权重是20
(唯一性是因为总权重不超过20的其它子图确实都不连通)
既然最小生成树唯一,Kruskal算法当然也会产生同一棵树

3. 话说最小生成树的prim算法和kursual算法的区别

prim算法和kurskal算法解决的问题是相同的,都用来求最小生成树。从某一结点A出发,按照一定次序,经过中间结点集Q中的每一个结点,得到最短路径,称为最小生成树。
kurskal算法的核心思想就是“尽可能的选取短边”,按照长度从小到大依次加入生成树;prim算法引入一个概念——生长点(和非生长点),每次加入的最短边是与生长点相邻的最短边,初始状态下,唯一的一个点就是生长点,随着新边的加入,每次加入的边的末端就是生长点,若某一生长点已经没有相邻边可以加入,就回溯到上一级结点,加入新边,直到Q中的所有结点都加入图中。
一般教材编的都很清楚的,结合我这个,再看看书,相信你很快就会明白的。

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

Kruskal算法:
void Kruskal(Edge E[],int n,int e)
{
int i,j,m1,m2,sn1,sn2,k;
int vset[MAXE];
for (i=0;i<n;i++) vset[i]=i; //初始化辅助数组
k=1; //k表示当前构造最小生成树的第几条边,初值为1
j=0; //E中边的下标,初值为0
while (k<n) //生成的边数小于n时循环
{
m1=E[j].u;m2=E[j].v; //取一条边的头尾顶点
sn1=vset[m1];sn2=vset[m2]; //分别得到两个顶点所属的集合编号
if (sn1!=sn2) //两顶点属于不同的集合,该边是最小生成树的一条边
{
printf(" (%d,%d):%d/n",m1,m2,E[j].w);
k++; //生成边数增1
for (i=0;i<n;i++) //两个集合统一编号
if (vset[i]==sn2) //集合编号为sn2的改为sn1
vset[i]=sn1;
}
j++; //扫描下一条边
}
}
Prim算法:
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;
}
}
}

5. 什么是最小生成树的prim算法

/*
邻接矩阵存储
测试数据
6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6
*/

#include <stdio.h>
#include <limits.h>
#define N 100

int p[N], key[N], tb[N][N];

void prim(int v, int n)
{
int i, j;
int min;

for (i = 1; i <= n; i++)
{
p[i] = v;
key[i] = tb[v][i];
}
key[v] = 0;
for (i = 2; i <= n; i++)
{
min = INT_MAX;
for (j = 1; j <= n; j++)
if (key[j] > 0 && key[j] < min)
{
v = j;
min = key[j];
}
printf("%d%d ", p[v], v);
key[v] = 0;
for (j = 1; j <= n; j++)
if (tb[v][j] < key[j])
p[j] = v, key[j] = tb[v][j];
}
}

int main()
{
int n, m;
int i, j;
int u, v, w;
while (scanf("%d%d", &n, &m))
{
for(i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
tb[i][j] = INT_MAX;
}

while (m--)
{
scanf("%d%d%d", &u, &v, &w);
tb[u][v] = tb[v][u] = w;
}
prim(1, n);
printf("\n");
}
return 0;
}

6. 用Prim算法求最小生成树

7. 利用Prim(普里姆)算法 构造最小生成树 程序

算法同样是解决最小生成树的问题。

其算法为:在这n个点中的相通的边进行排序,然后不断地将边添加到集合中(体现了贪心的算法特点),在并入集合之前,必须检查一下这两点是不是在一个集合当中,这就用到了并查集的知识。直到边的集合达到了n-1个。

与prim算法的不同:prim算法为单源不断寻找连接的最短边,向外扩展,即单树形成森林。而Kruskal算法则是不断寻找最短边然后不断将集合合并,即多树形成森林。

复杂度的不同:prim算法的复杂度是O(n^2),其中n为点的个数。Kruskal算法的复杂度是O(e*loge),其中e为边的个数。两者各有优劣,在不同的情况下选择不同的算法。

Prim算法用于求无向图的最小生成树

设图G =(V,E),其生成树的顶点集合为U。

①、把v0放入U。

②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。

③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。

其算法的时间复杂度为O(n^2)

Prim算法实现:

(1)集合:设置一个数组set(i=0,1,..,n-1),初始值为 0,代表对应顶点不在集合中(注意:顶点号与下标号差1)

(2)图用邻接阵表示,路径不通用无穷大表示,在计算机中可用一个大整数代替。
{先选定一个点,然后从该点出发,与该点相连的点取权值最小者归入集合,然后再比较在集合中的两点与其它各点的边的权值最小者,再次进入集合,一直到将所有的点都归入集合为止。}

8. 最小生成树是什么

1.生成树从前述的深度优先和广度优先遍历算法知,对于一个拥有n个顶点的无向连通图,它的边数一般都大于n-1。生成树是指在连通图中,由n个顶点和不构成回路的n-1条边构成的树。若由深度优先遍历得到的生成树称为深度优先生成树,则由广度优先遍历得到的生成树称为广度优先生成树。再进一步分析可知,对于满足条件,连通图的n个顶点和不构成回路的n-1条边构成的生成树有多棵,换言之,图的生成树不唯一。2.最小生成树对于带权的图,其生成树的边也带权,在这些带权的生成树中必有一棵边的权值之和最小的生成树,这棵生成树就是最小(代价)生成树。

最小生成树在实际中具有重要用途,如在通信网的设计中,用顶点表示城市,用边表示两个城市之间的通信线路,边的权值表示建造通信线路的费用,这n个城市之间最多可以建n(n-1)/2条线路。如果要求在任意两个城市之间都有线路相连,且建设费用最少,即从n(n-1)/2条边中选取权值最小的n-1条,这就是最小生成树问题。2.构造最小生成树的基本原则(1)尽可能选取权值最小的边,但不能构成回路。

(2)选择n-1条边构成最小生成树。

常见的最小生成树算法有普里姆(Prim)算法和克鲁斯卡尔(kruskal)算法两种。

9. 最小生成树 prim

"prim不是这样描述的吗?从一个点出发,列出这个点所有邻接的边,选择最小的边假如到树中,然后从另一个端点开始,一样操作就可以嘛?"--------应该是“从一个点出发,列出这个点所有邻接的边,选择最小的边,将所连顶点到树中,再到剩余的点中找与这两点(其中之一)距离最小的点加入之中。”然后循环就行了

热点内容
app怎么提供服务器地址 发布:2025-05-16 11:48:27 浏览:396
双面警长第一季ftp 发布:2025-05-16 11:41:20 浏览:664
php取数组第一个 发布:2025-05-16 11:30:58 浏览:423
解调算法 发布:2025-05-16 11:21:09 浏览:136
python密码暴力破解 发布:2025-05-16 11:13:28 浏览:592
倒角刀编程 发布:2025-05-16 11:12:55 浏览:350
数据库的酸性 发布:2025-05-16 11:03:17 浏览:124
phpmysql长连接 发布:2025-05-16 10:51:50 浏览:734
android横屏全屏 发布:2025-05-16 10:47:43 浏览:475
服务器直链下载搭建 发布:2025-05-16 10:47:38 浏览:176