最小生成树之算法记录【prime算法+Kruskal算法】【模板】
首先说一下什么是树:
1、只含一个根节点
2、任意两个节点之间只能有一条或者没有线相连
3、任意两个节点之间都可以通过别的节点间接相连
4、除了根节点没一个节点都只有唯一的一个父节点
5、也有可能是空树(不含任何节点)
最小生成树就是:
在所有数据满足是一棵树的情况下一条将所有节点都连接起来且长度最短的一条路(因为任意两个节点之间有权值
(相连的两点之间权值为一个具体的数,不相连的两个点之间权值为无穷大))
下面介绍通用的求最小生成树的两种算法:
ps:这里用的两种算法都是用邻接矩阵实现适合点稠密型数据或者数据较小的情况:
(1)prime算法:
/*
* 数组tree[]用来记录最小生成树的节点
* 数组lowdis[]记录从起点到其余所有点的距离并不断更新
* 数组map[][]记录所有数据两点之间的距离
* point是所有节点的数目,begin是起点
* mindis是最小生成树的长度
*/
void
prime()
{
int
i,j,min,mindis=0,next;
memset(tree,0,
sizeof
(tree));
for
(i=1;i<=point;i++)
{
lowdis[i]=map[begin][i];
//用lowdis[]数组记录下从起点到剩下所有点的距离
}
tree[begin]=1;
//标记起点(即最小生成树中的点)
for
(i=1;i<point;i++)
{
min=INF;
for
(j=1;j<=point;j++)
{
if
(!tree[j]&&min>lowdis[j])
{
min=lowdis[j];
//求出从当前起点到其余所有点的距离中最短的
next=j;
}
}
mindis+=min;
//记录下整条最小树的长度
tree[next]=1;
for
(j=1;j<=point;j++)
{
if
(!tree[j]&&lowdis[j]>map[next][j])
lowdis[j]=map[next][j];
//更新lowdis[]数组
}
}
printf(
"%d\n"
,mindis);
}
kruskal算法:
此算法的核心就是在并查集(并查集知识请看 知识小总结记录分类中的并查集(http://www.cnblogs.com/tonghao/p/4442821.html))的基础上对两点之间距离进行排序:
find()函数用来查找根节点
int
find(
int
father)
//查找根节点
{
int
t;
int
children=father;
while
(father!=
set
[father])
father=
set
[father];
while
(fa!=
set
[children])
{
t=
set
[children];
set
[children]=father;
children=t;
}
return
father;
}
void
mix(
int
x,
int
y)
//将两个点合并(即另两点根节点相同)
{
int
fx;
int
fy;
fx=find(x);
fy=find(y);
if
(fx!=fy)
set
[fx]=fy;
}
利用结构体排序:
struct
record
{
int
begin;
//记录两个点中的一个
int
end;
//记录两个点中的一个
int
dis;
//记录两点之间距离
}num[MAX];
bool
cmp(
int
a,
int
b)
{
return
a.dis<b.dis;
//对两点之间距离进行从大到小的排序
}