C++代码,数据结构-最小生成树的两个算法,Prime&Kruskal
来源:互联网 发布:软件系统分为 编辑:程序博客网 时间:2024/05/18 02:24
#include<iostream>#include<vector>#include<iterator>#include<queue>using namespace std;//图的数组(邻接矩阵)存储表示,最小生成树,#define INFINITY INT_NAX#define Max_v 20#include<fstream>typedef enum{dg,dn,udg,udn}Graphkind;struct Arccell{int adj;string *info;};typedef Arccell adjmatric[Max_v][Max_v];struct Mgraph{char vexs[Max_v]; //顶点向量adjmatric arcs; //邻接矩阵int vexnum,arcnum; //顶点数 和 弧数Graphkind kind; // 图的种类标志};int locate(Mgraph G,char ch){for(int i=0;i!=G.vexnum;++i){ if(G.vexs[i]==ch)return i;}}void createUDG(Mgraph &G){//采用数组表示法,构造无向图G cout<<"Please enter the vexnum and arcnum of the G graph"<<endl; cin>>G.vexnum>>G.arcnum; cout<<"Please enter the dians of G"<<endl; for(int i=0;i!=G.vexnum;++i){cin>>G.vexs[i];}//构造顶点向量 for(int i=0;i!=G.vexnum;++i){//初始化矩阵 for(int j=0;j!=G.vexnum;++j){ G.arcs[i][j].adj=10000; G.arcs[i][j].info=NULL; } }char v1,v2;int w;cout<<"Please enter "<<G.arcnum<<" arcnums"<<endl;for(int k=0;k!=G.arcnum;++k){ cin>>v1>>v2>>w; int i=locate(G,v1); int j=locate(G,v2); G.arcs[i][j].adj=w; G.arcs[j][i].adj=w;}}void printgraph(Mgraph M){cout<<"\n"<<"The graph has "<<M.vexnum<<"vertex and "<<M.arcnum<<"arc"<<endl;cout<<"The vertex is:"; for(int i=0;i!=M.vexnum;++i){cout<<M.vexs[i]<<" ";}cout<<endl; for(int i=0;i!=M.vexnum;++i){ for(int j=0;j!=M.vexnum;++j){ if(M.arcs[i][j].adj!=-1) cout<<M.vexs[i]<<" "<<M.vexs[j]<<endl; } } for(int i=0;i!=M.vexnum;++i){ for(int j=0;j!=M.vexnum;++j){ cout<<M.arcs[i][j].adj<<" "; }cout<<endl; }}//Prim算法构造最小生成树struct cedge{char adjvex;int lowcost; //权值};typedef cedge closedges[1000];//辅助数组closedges closedge;int minimum(closedges c,int n){ int mi=10000,tem;for(int i=0;i!=n;++i){ if(c[i].lowcost<mi&&c[i].lowcost!=0){ mi=c[i].lowcost; tem=i; }}return tem;}void Mini_tree_prime(Mgraph G,char u){//算法7.9. prime 算法int k=locate(G,u);for(int i=0;i!=G.vexnum;++i){ if(i!=k) { closedge[i].adjvex=u; closedge[i].lowcost=G.arcs[i][k].adj; }}closedge[k].lowcost=0;for(int i=1;i<G.vexnum;++i){ k=minimum(closedge,G.vexnum); cout<<closedge[k].adjvex<<" "<<G.vexs[k]<<endl; closedge[k].lowcost=0; for(int j=0;j!=G.vexnum;++j){ if(G.arcs[k][j].adj<closedge[j].lowcost) { closedge[j].adjvex=G.vexs[k]; closedge[j].lowcost=G.arcs[k][j].adj; } }}}//克鲁斯卡尔算法,利用并查集,边集数组struct edge{int beg;int ends;int weight;};struct parent{//并查集。void initialize()//初始化{ for(int i=0;i!=100;++i){ parents[i]=-1; }}int finds(int x){//查找x元素所在的集合 if(parents[x]==-1)return x; else return parents[x]=finds(parents[x]);}bool merges(int n,int m){ //两个点的所在集合,若相同则返回false;若不同,数字大的集合归到数字小的集合,返回trueif(n==m){ return false;}else if(n<m){ parents[m]=n;return 1;}else{ parents[n]=m; return 1;}}int parents[100];};void mini_tree_Kruskal(Mgraph G)//克鲁斯卡尔算法{edge edges[G.arcnum];//边集数组parent par;par.initialize();//初始化 int counts=0;for(int i=0;i!=G.vexnum;++i){ //把邻接矩阵转化为边集数组 for(int j=G.vexnum-1;j>i;--j){ if(G.arcs[i][j].adj!=10000){ edges[counts].beg=i; edges[counts].ends=j; edges[counts].weight=G.arcs[i][j].adj; ++counts; } }}for(int i=0;i!=G.arcnum;++i){//正确的应该只需要执行到包括所有点即可,但将每条边都进行一遍不影响结果, int tem,maxx=1000; for(int j=0;j!=G.arcnum;++j){ if(edges[j].weight<maxx){ maxx=edges[j].weight; tem=j; } }edges[tem].weight=1001;int m= par.finds(edges[tem].beg);int n= par.finds(edges[tem].ends);if(par.merges(m,n)){//如何不形成回路则输出这条边 cout<<G.vexs[edges[tem].beg]<<" "<<G.vexs[edges[tem].ends]<<endl;}}}int main(){ ifstream infile("rebuf.txt");cin.rdbuf(infile.rdbuf()); Mgraph m; createUDG(m);printgraph(m);cout<<endl;Mini_tree_prime(m,'a');cout<<endl;cout<<endl;mini_tree_Kruskal(m); return 0;}
两个算法在思想理解上 都是相对简单的,但是在转化为代码实现的过程中有一定的难度,
prime算法用到了一个辅助数组,
而Kruskal算法用到了并查集的东西,并查集数据结构书上也没有讲,于是自己网上了查理资料,发现是一种神奇的数据结构, 数据简单但是应用很广泛,自己算是刚刚接触了查并集,对其其他的应用还有待学习,
在Kruskal算法中利用查并集来判断此时加上权值最小的一边是否形成回路,这是kruskal算法中最难的部分,
先用
void initialize()//初始化{ for(int i=0;i!=100;++i){ parents[i]=-1; }}使得parents这个并查集初始化,各单点的集合根都为-1
然后利用
int finds(int x){//查找x元素所在的集合 if(parents[x]==-1)return x; else return parents[x]=finds(parents[x]);}找出点x所在的集合,若x还未属于任何一个集合,即parents[x]=-1,则令其为自己单个元素为集合,
最后通过
bool merges(int n,int m){ //两个点的所在集合,若相同则返回false;若不同,数字大的集合归到数字小的集合,返回trueif(n==m){ return false;}else if(n<m){ parents[m]=n;return 1;}else{ parents[n]=m; return 1;}}merges判断,若此时边的两点都属于同一个集合,那么返回false;
如果不同则约定集合根数字大的集合接到集合根数字上的上去,并为一个集合,并返回true,输出该边,
0 0
- C++代码,数据结构-最小生成树的两个算法,Prime&Kruskal
- 最小生成树---Kruskal/Prime算法
- 最小生成树算法[Prime/(Kruskal)]
- 最小生成树的prime和kruskal算法
- 数据结构(C实现)------- 最小生成树之Kruskal算法
- Kruskal最小生成树算法代码实现(c++)
- 最小生成树(kruskal算法)和 (Prime算法)
- 图论-最小生成树-prime算法&Kruskal算法 c++
- EOJ2067 最小生成树 prime算法+kruskal算法
- 数据结构:最小生成树--Kruskal算法
- 数据结构之最小生成树 Kruskal算法
- 数据结构 最小生成树 Kruskal算法
- 数据结构:最小生成树--Kruskal算法
- 数据结构——邻接矩阵的最小生成树Kruskal算法
- 求图的最小生成树的prime算法和Kruskal算法
- Kruskal算法求图的最小生成树的完整C代码
- 最小生成树kruskal算法的代码实现
- 最小生成树的Kruskal算法java代码实现
- ios开发论坛苹果正式发布iPhone 5C和5S
- 页面统计数据库表建立访问
- AD6使用若干使用中的11个技巧
- 深复制、浅复制、retain
- mysql root密码修复
- C++代码,数据结构-最小生成树的两个算法,Prime&Kruskal
- error: more than one device and emulator .
- 在代码里面设置组件的相对位置
- 操作系统课堂笔记(5)存储管理
- 程序两种空间的切换
- 跟我一起写 Makefile(十四)
- 使用Google Weather API查询天气预报
- Windows服务
- Android AIDL简单例子