最小生成树算法(Prim和Kruskal)
2015-03-10 16:44
274 查看
无向连通图的最小生成树
设G=(V,E)是一个无向连通图,生成树上各边的权值之和称为该生成树的代价,在G的所有生成树中,代价最小的生成树即为其最小生成树。
Prim(普里姆)算法的基本思想是:
设 G=(V,E) 是一个无向连通图,令T=(U,TE) 是 G 的最小生成树。T的初始状态为 U={v0}(v0∈V),TE={},然后重复执行下述操作:
在所有 u∈U,v∈V-U 的边中找一条代价最小的边(u,v) 并入 U,直至 U=V 为止。此时TE中必有 n-1 条边,T 就是最小生成树。
代码如下:
[cpp] view
plaincopy
void MiniSpanTree(MGraph G)
{
int min,i,j,k;
int adjvex[MAXVEX];//保存相关顶点下标
int lowcost[MAXVEX];//保存相关顶点间边的权值
adjvex[0] = 0;//初始化第一个顶点下标为0
lowcost[0] = 0;//初始化第一个权值为0,即Vo加入生成树
//lowcost的值为0,表示此下标的顶点已经加入生成树
for (i = 1; i < G.vertexNum; i++)//循环除0外的全部顶点
{
lowcost[i] = G.arc[0][i];//将Vo顶点与之有边的权值存入数组
adjvex[i] = 0;//初始化都为Vo的下标
}
for (i = 1; i < G.vertexNum; i++)
{
min = INFINITE;//初始最小值为极大∞
j = 1;
k = 0;
while (j < G.vertexNum)//循环全部顶点
{
if (lowcost[j] != 0 && lowcost[j] < min)//如果权值不为0且小雨min
{
min = lowcost[j];//让当前权值成为最小值
k = j;//将当前最小值的下标存入k
}
j++;
}
printf("(%d,%d)",adjvex[k],k);//输出当前顶点边中权值最小边
lowcost[k] = 0;//0表示该顶点已完成
for (j = 1; j < G.vertexNum; j++)//循环所有顶点
{
//若下标为k的顶点的各边权值小于此前这些顶点未被加入生成树的权值
if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
{
lowcost[j] = G.arc[k][j];//将较小权值存入lowcost
adjvex[j] = k;//将下标为k的顶点存入adjvex
}
}
}
}
Kruskal(克鲁斯卡尔)算法的基本思想是:
基本思想:设无向连通网为 G=(V, E),令 G 的最小生成树为 T=(U, TE),其初态为 U=V,TE={ },然后,按照边的权值由小到大的顺序,考察 G 的边集E中的各条边。若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T中的连通分量个数为1时,此连通分量便为 G 的一棵最小生成树。
代码如下:
[cpp] view
plaincopy
/对边集数组Edge结构的定义
typedef struct
{
int begin;
int end;
int weight;
}Edge;
void MiniSpanTree(MGraph G)
{
int i,n,m;
Edge edges[MAXEDGE];//定义边集数组
int parent[MAXVEX];//定义一数组用来判断边与边是否形成环路
//此处省略将邻接矩阵G转化为边集数组edges并按权值由小到大排序的代码
for (i = 0; i < G.vertexNum; i++)
parent[i] = 0;//初始化为0
for (i = 0; i < G.edgeNum; i++)//循环每一条边
{
n = Find(parent,edges[i].begin);
m = Find(parent,edges[i].end);
if (n != m)//假如n与m不相等,说明此边没有与现有的生成树形成环路
{
parent
= m;//将此边的结尾顶点放入下标为起点的parent中,表示此顶点已经在生成树中
printf("(%d,%d) %d ",edges[i].begin,edges[i].end,edges[i].weight);
}
}
}
int Find(int * parent,int x)//查找连线顶点的尾部下标
{
while (parent[x] > 0)
x = parent[x];
return x;
设G=(V,E)是一个无向连通图,生成树上各边的权值之和称为该生成树的代价,在G的所有生成树中,代价最小的生成树即为其最小生成树。
Prim(普里姆)算法的基本思想是:
设 G=(V,E) 是一个无向连通图,令T=(U,TE) 是 G 的最小生成树。T的初始状态为 U={v0}(v0∈V),TE={},然后重复执行下述操作:
在所有 u∈U,v∈V-U 的边中找一条代价最小的边(u,v) 并入 U,直至 U=V 为止。此时TE中必有 n-1 条边,T 就是最小生成树。
代码如下:
[cpp] view
plaincopy
void MiniSpanTree(MGraph G)
{
int min,i,j,k;
int adjvex[MAXVEX];//保存相关顶点下标
int lowcost[MAXVEX];//保存相关顶点间边的权值
adjvex[0] = 0;//初始化第一个顶点下标为0
lowcost[0] = 0;//初始化第一个权值为0,即Vo加入生成树
//lowcost的值为0,表示此下标的顶点已经加入生成树
for (i = 1; i < G.vertexNum; i++)//循环除0外的全部顶点
{
lowcost[i] = G.arc[0][i];//将Vo顶点与之有边的权值存入数组
adjvex[i] = 0;//初始化都为Vo的下标
}
for (i = 1; i < G.vertexNum; i++)
{
min = INFINITE;//初始最小值为极大∞
j = 1;
k = 0;
while (j < G.vertexNum)//循环全部顶点
{
if (lowcost[j] != 0 && lowcost[j] < min)//如果权值不为0且小雨min
{
min = lowcost[j];//让当前权值成为最小值
k = j;//将当前最小值的下标存入k
}
j++;
}
printf("(%d,%d)",adjvex[k],k);//输出当前顶点边中权值最小边
lowcost[k] = 0;//0表示该顶点已完成
for (j = 1; j < G.vertexNum; j++)//循环所有顶点
{
//若下标为k的顶点的各边权值小于此前这些顶点未被加入生成树的权值
if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
{
lowcost[j] = G.arc[k][j];//将较小权值存入lowcost
adjvex[j] = k;//将下标为k的顶点存入adjvex
}
}
}
}
Kruskal(克鲁斯卡尔)算法的基本思想是:
基本思想:设无向连通网为 G=(V, E),令 G 的最小生成树为 T=(U, TE),其初态为 U=V,TE={ },然后,按照边的权值由小到大的顺序,考察 G 的边集E中的各条边。若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T中的连通分量个数为1时,此连通分量便为 G 的一棵最小生成树。
代码如下:
[cpp] view
plaincopy
/对边集数组Edge结构的定义
typedef struct
{
int begin;
int end;
int weight;
}Edge;
void MiniSpanTree(MGraph G)
{
int i,n,m;
Edge edges[MAXEDGE];//定义边集数组
int parent[MAXVEX];//定义一数组用来判断边与边是否形成环路
//此处省略将邻接矩阵G转化为边集数组edges并按权值由小到大排序的代码
for (i = 0; i < G.vertexNum; i++)
parent[i] = 0;//初始化为0
for (i = 0; i < G.edgeNum; i++)//循环每一条边
{
n = Find(parent,edges[i].begin);
m = Find(parent,edges[i].end);
if (n != m)//假如n与m不相等,说明此边没有与现有的生成树形成环路
{
parent
= m;//将此边的结尾顶点放入下标为起点的parent中,表示此顶点已经在生成树中
printf("(%d,%d) %d ",edges[i].begin,edges[i].end,edges[i].weight);
}
}
}
int Find(int * parent,int x)//查找连线顶点的尾部下标
{
while (parent[x] > 0)
x = parent[x];
return x;
相关文章推荐
- 图的广度遍历、深度遍历及最小生成树书算法(Prim、Kruskal)
- 算法记录---最小生成树【kruskal&&prim】
- 最小生成树 ,prim 和Kruskal 算法
- 算法复习 - 最小生成树算法 Prim、Kruskal(普里姆算法、 克鲁斯卡尔算法)
- 图论中最小生成树算法-Prim(普里姆)算法、kruskal(克鲁斯卡尔避圈法)算法、破圈算法
- 最小生成树 Prim(普里姆)算法和Kruskal(克鲁斯特尔)算法
- 数据结构 学习笔记(九):图(下):最小生成树(Prim,Kruskal 算法),拓扑排序 AOV,关键路径 AOE
- 最小生成树的两种算法图解(Kruskal与prim)
- 最小生成树算法(Prim+Kruskal)
- hdu 1863 畅通工程 最小生成树模板入门题 prim+kruskal两种算法AC。
- 最小生成树算法(prim&kruskal)
- 最小生成树算法介绍(转载)Prim+Kruskal
- kruskal与prim最小生成树算法
- 最小生成树两种算法。kruskal和prim
- 最小生成树算法Prim、Kruskal
- 最小生成树算法(Prim和Kruskal)
- hdu 1162 Eddy's picture 最小生成树入门题 Prim+Kruskal两种算法AC
- 算法整理:最小生成树(mst)-Prim+Kruskal
- poj 1258 小白算法练习 Agri-Net 最小生成树 prim kruskal
- 数据结构之最小生成树的Prim和Kruskal`s 算法