最小生成树之算法记录【prime算法+Kruskal算法】【模板】

最小生成树之算法记录【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;
 mix函数用来合并两个节点,使两个节点的父节点相同

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; //对两点之间距离进行从大到小的排序
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值