Prim算法和Kruskal算法的基本思想和实现
来源:互联网 发布:linux ftp的宿主 编辑:程序博客网 时间:2024/06/06 06:45
这两个都是求最小生成树的算法,个人更喜欢Kruskal算法。
Prim算法
基本思想
有两个集合,A是空集,B集合里有现在图中的所有边。
将B中任意一点加入A集合,在这个点的所用通路中选择一个权值最小的边且这个边到的点不在B集合之中。然后将这个点加入A集合,再进行上述步骤,直到将B集合变成空集。
代码实现
#include<bits/stdc++.h>using namespace std;const int INF=1<<30;const int maxn=110;typedef struct { int mp[maxn][maxn]; int number;}Graph;void prim(Graph &a){ int min,i,j,k; int adj[maxn],lowcost[maxn]; lowcost[0]=0;//值为0代表已经放入A集合 adj[0]=0; for(int i=1;i<a.number;++i){ lowcost[i]=a.mp[0][i];//初始化lowcost和adj数组。lowcost代表现在点到各个点的距离 adj[i]=0; } for(int i=1;i<a.number;++i){ int min=INF; int j=1,k=0; while(j < a.number) { if( lowcost[j]!=0 && lowcost[j]<min){//在集合B中选出一个最小的边 min = lowcost[j]; k=j; } j++; } cout<<"("<<adj[k]<<","<<k<<")"<<endl; lowcost[k]=0; for(int j=1;j<a.number;++j){ if(lowcost[j]!=0 && a.mp[k][j]<lowcost[j]){ lowcost[j]=a.mp[k][j];//因为有新的点加入A集合,对应的数组更新 adj[j]=k; } } }}int main(){ freopen("in.txt","r",stdin); Graph a; int v,e,x,y,w; cin>>v>>e; a.number=v; for(int i=0;i<v;++i) for(int j=0;j<v;++j) a.mp[i][j]=INF; for(int i=0;i<v;++i) a.mp[i][i]=0; for(int i=0;i<e;++i){ cin>>x>>y>>w; a.mp[x][y]=w; a.mp[y][x]=w; } prim(a); return 0;}
Kruskal算法
基本思路
学习Kruskal算法需要前置知识:并查集,一个简单但实用的数据结构。
学习链接:并查集的基本思想和实现
将并查集应用在图上还需要另外一个数据结构:边集数组。
就是一个三位数组,里面存的是起始点,终止点,边权。
将这个数组以边权大小排序,小的在前。
然后按照顺序将数组中存的点连接起来,形成集合。而连起点的前提条件就是不属于一个集合。这个集合的判断就需要用到并查集了。在连接的时候也需要用到并查集进行合并。
直到将所有的点都合并为一个集合,循环结束。
代码实现
#include<bits/stdc++.h>using namespace std;const int maxn=110;typedef struct{ int begin,end,weight;}Edge;int FindSet(int x,int *father){ if(x!=father[x]) father[x]=FindSet(father[x],father); return father[x];}bool Union(int x,int y,int *father,int *rank){ x=FindSet(x,father); y=FindSet(y,father); if(x==y)//属于同一集合,不进行合并操作 return false; if(rank[x]>rank[y]) father[y]=x; else{ if(rank[x]==rank[y]) rank[y]++; father[x]=y; } return true;}bool cmp(Edge a,Edge b){ return a.weight<b.weight;}bool isfull(bool *flag,int n)//判断所有的点都属于一个集合了{ for(int i=0;i<n;++i){ if(!flag[i]) return false; } return true;}int main(){ // freopen("in.txt","r",stdin); Edge a[maxn]; bool flag[maxn]; int v,e; cin>>v>>e; memset(flag,false,sizeof(flag)); for(int i=0;i<e;++i) cin>>a[i].begin>>a[i].end>>a[i].weight; int father[maxn],rank[maxn]; for(int i=0;i<v;++i){ father[i]=i; rank[i]=0; } sort(a,a+e,cmp); for(int i=0;i<v;++i){ if(isfull(flag,v)) break; Union(a[i].begin,a[i].end,father,rank);//每次将两个集合进行合并 cout<<"("<<a[i].begin<<","<<a[i].end<<")"<<endl; flag[a[i].begin]=true; flag[a[i].end]=true; } return 0;}
阅读全文
0 0
- Prim算法和Kruskal算法的基本思想和实现
- 图的基本操作:Kruskal算法和Prim算法
- MST的Prim算法和Kruskal算法
- 【Prim算法和Kruskal算法的验证】
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- prim 算法和 kruskal算法
- Prim算法和Kruskal算法
- Prim算法和Kruskal算法
- Prim和Kruskal算法之C++实现
- POJ 3348 Cows (凸包)
- 往日不堪回首,今朝几多新愁
- 撤销修改
- [自然语言处理] 在NLP的路上越走越远(自然语言处理各类资源wiki)
- eclipse下载
- Prim算法和Kruskal算法的基本思想和实现
- Qt中的析构函数
- java中的全局变量与局部变量
- nginx
- Android 读取文件File的大小
- Android 5.1 SystemUi 之 StatusBar的简单分析
- Python装饰器为什么难理解?
- FPGA的LPM标准
- Linux 使用pwgen命令创建随机密码