最小生成树--Kruskal算法
2016-04-19 17:22
369 查看
与Prim算法不同,Kruskal算法基于并查集和贪心算法,利用并查集判断其是否存在循环。
Kruskal算法基本思想: 对所有边进行排序,优先选取权重小的边,并同时判断其是否联通(利用并查集判断)
数据结构:结构体数组
算法思想:快排,贪心,递归
用结构体来储存边
利用快排排序:
利用并查集来判断是否是形成联通环:
最后利用贪心把边一条条符合条件的边放入集合中:
来看全部代码的实现:
其实这个算法和prim算法中,都包含了贪心算法的思想,只是实现的方式不同。
Kruskal算法基本思想: 对所有边进行排序,优先选取权重小的边,并同时判断其是否联通(利用并查集判断)
数据结构:结构体数组
算法思想:快排,贪心,递归
用结构体来储存边
typedef struct edge{ int u;//顶点 int v;//末点 int w;//权重 }EDGE; EDGE e[100];
利用快排排序:
void sort(int left,int right) { int i,j; EDGE t; if(left>right) return ; i=left; j=right; while(i!=j) { while(e[j].w>=e[left].w&&i<j) j--; while(e[i].w<=e[left].w&&i<j) i++; if(i<j) { t=e[i]; e[i]=e[j]; e[j]=t; } } t=e[i]; e[i]=e[left]; e[left]=t; sort(left,i-1); sort(i+1,right); return ; }
利用并查集来判断是否是形成联通环:
int merge(int x,int y) { int i=getf(x); int j=getf(y); if(i!=j)//如果不相同则利用偏左原则 { f[j]=i;//把祖宗更变 return 1; } else return 0; } int getf(int v)//利用递归找祖先 { if(v==f[v]) return v; else { f[v]=getf(f[v]); return f[v]; } }
最后利用贪心把边一条条符合条件的边放入集合中:
for(i=1;i<=m;i++) { if(merge(e[i].u,e[i].v)) { sum+=e[i].w;//如果不在一个集合中,则把边放入 count++;//计数器 } if(count==n-1) break; }
来看全部代码的实现:
#include<stdio.h>
#include<string.h>
#include<conio.h>
int f[100];
int n,m,sum,count;
typedef struct edge{ int u;//顶点 int v;//末点 int w;//权重 }EDGE; EDGE e[100];
int getf(int v);
void sort(int left,int right);
int merge(int x,int y);
int main()
{
int i,j;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++) f[i]=i;//初始化并查集
for(i=1;i<=m;i++)
scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
sort(1,m);
for(i=1;i<=m;i++)
{
if(merge(e[i].u,e[i].v))
{
sum+=e[i].w;//如果不在一个集合中,则把边放入
count++;//计数器
}
if(count==n-1)
break;
}
printf("%d",sum);
return 0;
}
void sort(int left,int right) { int i,j; EDGE t; if(left>right) return ; i=left; j=right; while(i!=j) { while(e[j].w>=e[left].w&&i<j) j--; while(e[i].w<=e[left].w&&i<j) i++; if(i<j) { t=e[i]; e[i]=e[j]; e[j]=t; } } t=e[i]; e[i]=e[left]; e[left]=t; sort(left,i-1); sort(i+1,right); return ; }
int merge(int x,int y)
{
int i=getf(x);
int j=getf(y);
if(i!=j)//如果不相同则利用偏左原则
{
f[j]=i;//把祖宗更变
return 1;
}
else
return 0;
}
int getf(int v)//利用递归找祖先
{
if(v==f[v])
return v;
else
{
f[v]=getf(f[v]);
return f[v];
}
}
其实这个算法和prim算法中,都包含了贪心算法的思想,只是实现的方式不同。
相关文章推荐
- iOS应用程序打包
- spring依赖注入原理的简单模拟
- LINQ To DataSet 示例
- 跳转时候提示Attempt to present on while a presentation is in progress
- SqlServer查询表中各列名称、表中列数
- 公司开源框架技术连接
- Mysql join语句解析
- android开发之onCreate( )方法详解
- 图形统计报表EChart的使用
- VRRP技术详解
- Ajax实现简单下拉选项效果【推荐】
- WebLogic的部署模式:开发模式、生产模式区别及相互转换的方法
- ViewPager源码不完全解读
- nyoj 117 求逆序数
- 开启MYSQL主从同步备份
- 题目1522:包含min函数的栈
- 80. Remove Duplicates from Sorted Array II
- 武校学生
- 第八周项目1—数组做数据成员(工资类、数组)
- UIScrollView contentInset contentOffset contentSize 详解