无向连通网的最小生成树算法[第3部分]
来源:互联网 发布:数组splice 删除 编辑:程序博客网 时间:2024/05/29 13:57
普利姆算法的测试数据如下:每行数据表示边的两个端点和权值10 131 0 42 1 23 0 34 3 85 1 25 2 25 4 16 3 107 4 48 5 48 7 69 6 59 7 2
普利姆最小生成树算法:
/* 时间:2017.1.1 描述:普利姆算法求解最小生成树*/#include<iostream>#include<climits>#include<cstdio>#include<iomanip>#include<cstring>#include<fstream>#define INF INT_MAX#define FILEINPUT 1using namespace std;typedef struct edgeNode{ int from,to; int cost;}EDGENODE;void creatMatrix(int **AdjMatrix,int n,int e); //构建无向图的邻接矩阵void printMatrix(int **AdjMatrix,int n); //输出图的邻接矩阵void initEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int start); //初始化边集int chooseEdge(EDGENODE *edgeSet,int n,int index); //从候选边集中选取权重最小的边void modfiyEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int index,int to);//调整候选边集void primMst(int **AdjMatrix,EDGENODE *edgeSet,int n,int start); //普利姆算法void printMst(EDGENODE *edgeSet,int n); //输出最小生成树选举结果int main(){ //freopen("data.txt","r",stdin); #if FILEINPUT //条件编译:输入重定向到文件(输入邻接矩阵数据) ifstream fin("data.txt"); streambuf *strm_buf=cin.rdbuf(); cin.rdbuf(fin.rdbuf()); #endif int i,n,e,start; int **AdjMatrix; //存储邻接矩阵 EDGENODE *edgeSet; //存储最小生成树选的边集 cout<<"Enter the number of nodes and edges:"<<endl; cin>>n>>e; AdjMatrix=(int **)malloc(sizeof(int *)*n); //为邻接矩阵分配存储空间 for(i=0;i<n;i++) AdjMatrix[i]=(int *)malloc(sizeof(int)*n); edgeSet=(EDGENODE *)malloc(sizeof(EDGENODE)*n); //为最小生成树边集合配存储空间 creatMatrix(AdjMatrix,n,e); //构建无向图的邻接矩阵 printMatrix(AdjMatrix,n); //输出图的邻接矩阵 #if FILEINPUT //条件编译:输入重定向到键盘(输入普利姆算法的起始顶点) cin.rdbuf(strm_buf); #endif while(1) { cout<<"Enter the start position of the Graph: "; cin>>start; primMst(AdjMatrix,edgeSet,n,start); printMst(edgeSet,n); } #if FILEINPUT //条件编译:输入重定向到键盘(输入普利姆算法的起始顶点) fin.close(); #endif return 0;}void creatMatrix(int **AdjMatrix,int n,int e){ int i,j,from,to,cost; for(i=0;i<n;i++) for(j=0;j<n;j++) AdjMatrix[i][j]=INF; cout<<"<from----to----cost>"<<endl; for(i=0;i<e;i++) { cin>>from>>to>>cost; AdjMatrix[from][to]=cost; AdjMatrix[to][from]=cost; }}void printMatrix(int **AdjMatrix,int n){ int i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) if(AdjMatrix[i][j]==INF) cout<<setiosflags(ios::left)<<setw(6)<<"INF"; else cout<<setiosflags(ios::left)<<setw(6)<<AdjMatrix[i][j]; cout<<endl; }}void initEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int start){ int i,index=0; for(i=0;i<n;i++) if(i!=start) { edgeSet[index].from=start; edgeSet[index].to=i; edgeSet[index].cost=AdjMatrix[start][i]; index++; }}int chooseEdge(EDGENODE *edgeSet,int n,int index){ int minCost=INF,minPos,i; for(i=index;i<n-1;i++) if(edgeSet[i].cost<minCost) { minCost=edgeSet[i].cost; minPos=i; } if(minCost==INF) { cout<<"The Graph is disconnected!"<<endl; exit(1);//图不连通,程序结束 } return minPos;}void modfiyEdgeSet(int **AdjMatrix,EDGENODE *edgeSet,int n,int index,int to){ int i,cost; for(i=index;i<n-1;i++) { cost=AdjMatrix[to][edgeSet[i].to]; if(cost<edgeSet[i].cost) { edgeSet[i].cost=cost; edgeSet[i].from=to; } }}void primMst(int **AdjMatrix,EDGENODE *edgeSet,int n,int start){ int iter,minPos,to; EDGENODE edge; initEdgeSet(AdjMatrix,edgeSet,n,start); //初始化边集合 for(iter=0;iter<n-1;iter++) { minPos=chooseEdge(edgeSet,n,iter); //从边集中选择取值最小边 edge=edgeSet[minPos]; //将选择的最小边edgeSet[iter] edgeSet[minPos]=edgeSet[iter]; edgeSet[iter]=edge; to=edgeSet[iter].to; //将选择的边结点加入U集合 modfiyEdgeSet(AdjMatrix,edgeSet,n,iter,to);//调整候选边结点 }}void printMst(EDGENODE *edgeSet,int n){ int index; int totalCost=0; for(index=0;index<n-1;index++) { cout<<"("<<edgeSet[index].from<<","<<edgeSet[index].to<<") "<<edgeSet[index].cost<<endl; totalCost+=edgeSet[index].cost; } cout<<"totalCost: "<<totalCost<<endl;}
克鲁斯科尔算法的测试数据:第一行表示图的顶点数和边数;从第二行开始表示表的顶点编号和权值10 130 1 41 2 20 3 33 4 81 5 22 5 24 5 13 6 104 7 45 8 47 8 66 9 57 9 2
克鲁萨卡尔算法:
/* 时间:2017.1.1 描述:结合并查集实现克鲁斯卡尔算法求最小生成树*/#include<iostream>#include<climits>#include<iomanip>#include<cstring>#include<fstream>#include<algorithm>#define INF INT_MAX#define FILEINPUT 1using namespace std;typedef struct edgeNode{ int from,to; int cost;}EDGENODE;bool operator<(const EDGENODE &a,const EDGENODE &b){ if(a.cost!=b.cost) return a.cost<b.cost; else if(a.from!=b.from) return a.from<b.from; else return a.to<b.to;}int flag[512];void creatMatrix(int **AdjMatrix,EDGENODE *edgeSet,int n,int e);void printMatrix(int **AdjMatrix,int n);void printEdgeSet(EDGENODE *edgeSet,int e);void kruskalMst(EDGENODE *edgeSet,int n,int e);int findRootEdge(int nodeNumber);int mergeEdge(int nodeFrom,int nodeTo);int main(){ //freopen("data.txt","r",stdin); #if FILEINPUT //条件编译:输入重定向到文件(输入邻接矩阵数据) ifstream fin("data.txt"); streambuf *strm_buf=cin.rdbuf(); cin.rdbuf(fin.rdbuf()); #endif int i,n,e; int **AdjMatrix; //存储邻接矩阵 EDGENODE *edgeSet; //边集合 cout<<"Enter the number of nodes and edges:"<<endl; cin>>n>>e; AdjMatrix=(int **)malloc(sizeof(int *)*n); //为邻接矩阵分配存储空间 for(i=0;i<n;i++) AdjMatrix[i]=(int *)malloc(sizeof(int)*n); edgeSet=(EDGENODE *)malloc(sizeof(EDGENODE)*e); //为边集合分配存储空间 for(i=0;i<n;i++) //初始化并查集 flag[i]=i; creatMatrix(AdjMatrix,edgeSet,n,e); printMatrix(AdjMatrix,n); kruskalMst(edgeSet,n,e); #if FILEINPUT //条件编译:输入重定向到键盘(输入普利姆算法的起始顶点) cin.rdbuf(strm_buf); fin.close(); #endif return 0;}void creatMatrix(int **AdjMatrix,EDGENODE *edgeSet,int n,int e){ int i,j,from,to,cost; EDGENODE edge; for(i=0;i<n;i++) for(j=0;j<n;j++) AdjMatrix[i][j]=INF; cout<<"<from----to----cost>"<<endl; for(i=0;i<e;i++) { cin>>from>>to>>cost; AdjMatrix[from][to]=cost; AdjMatrix[to][from]=cost; edge.from=from; edge.to=to; edge.cost=cost; edgeSet[i]=edge; }}void printMatrix(int **AdjMatrix,int n){ int i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(AdjMatrix[i][j]==INF) cout<<setiosflags(ios::left)<<setw(6)<<"INF"; else cout<<setiosflags(ios::left)<<setw(6)<<AdjMatrix[i][j]; } cout<<endl; }}void printEdgeSet(EDGENODE *edgeSet,int e){ int index=0; for(index=0;index<e;index++) cout<<"("<<edgeSet[index].from<<","<<edgeSet[index].to<<") "<<edgeSet[index].cost<<endl;}int findRootEdge(int nodeNumber) { int i,j,root; root=nodeNumber; while (flag[root]!=root) //循环结束,则找到同一边集中的最小结点编号 root= flag[root]; i=nodeNumber; while(i!=root) //本循环修改查找路径中所有边结点编号 { j=flag[i]; flag[i]=root; i=j; } return root;}int mergeEdge(int nodeFrom,int nodeTo) //边结点合并到连通图中{ int indexFrom=findRootEdge(nodeFrom); int indexTo=findRootEdge(nodeTo); if(flag[indexFrom]<flag[indexTo]) flag[indexTo]=indexFrom; else flag[indexFrom]=indexTo; if(indexFrom==indexTo) return 1; else return 0;}void kruskalMst(EDGENODE *edgeSet,int n,int e){ int index=0; int countEdge=0; int minCost=0; //cout<<"------------------------------------"<<endl; //printEdgeSet(edgeSet,e); sort(edgeSet,edgeSet+e); //对边集进行快速排序 //cout<<"------------------------------------"<<endl; //printEdgeSet(edgeSet,e); //cout<<"------------------------------------"<<endl; while(index<e) { int from=edgeSet[index].from; int to=edgeSet[index].to; int cost=edgeSet[index].cost; if(mergeEdge(from,to)==0) //利用并查集判断环路,同时对查找路径进行压缩合并 { countEdge++; minCost+=cost; cout<<"("<<from<<","<<to<<") "<<cost<<endl; index++; } else { index++; } if(countEdge==n-1) { break; } } if(index<e) cout<<"minCost: "<<minCost<<endl; else { cout<<"The Graph is disconnected!"<<endl; //index>=e则不能构造最小生成树 }}
0 0
- 无向连通网的最小生成树算法[第3部分]
- 无向连通网的最小生成树算法[第1部分]
- 无向连通网的最小生成树算法[第2部分]
- 无向连通网的最小生成树
- 求无向连通图的最小生成树算法——Prim与Kruska
- 无向网的最小生成树(Prim算法)
- 无向网的最小生成树(Kruskal算法)
- 无向网图的最小生成树--普里姆算法
- Prim求无向连通图最小生成树
- prime算法求无向图的最小生成树
- 无向图的最小生成树(prim算法)
- 求无向连通图的最小生成树算…
- 无向网图的最小生成树算法--克鲁斯卡尔算法
- 数据结构(18)--Prim算法求解无向网的最小生成树
- 【数据结构】算法7.7-7.8 无向图的连通分量和生成树
- 无向网图的最小生成树---完整代码
- 无向连通图的生成树个数
- 无向图的连通分量和生成树
- 油脂
- Java中==与equals方法的区别
- IO多路复用——select()
- 如何启动/停止/重启MySQL
- EF 汇总函数使用注意事项Max()/Min()等
- 无向连通网的最小生成树算法[第3部分]
- 降血糖
- 6.1 Hadoop MongoDB案例
- bzoj 1004: [HNOI2008]Cards 置换群+dp
- 水环境
- jsp+servlet一、jsp九大内置对象以及乱码处理
- Inside the Linux boot process
- 这要放到现在,妥妥的UC小编
- Java中violate关键字的含义