1.krusual算法通过边生成有权不分方向的图中最小生成树,第一点:建立一个从小到大排序的数组(Krusual的生成数组);第二点:通过集合中并操作,对新加入的边(对新加入顶点通过集合的Union操作防止产生环路)。
#include<iostream> using namespace std; //Krusual算法的理解,依次从边中挑选出不形成回路的边形成森林 typedef char VerterType; //使用邻接矩阵 #define MAxSize 20 int father[MAxSize],son[MAxSize]; //father表示每一个节点的父节点 typedef struct Graph{ int VerterNum,edgenum; VerterType ver[MAxSize]; int edge[MAxSize][MAxSize]; }Graph; //定义一个边集结构,用来存储图上边的信息 //存储生成图,经过排序之后的边上的图,采用集概念防止其产生回路 typedef struct gEdge{ int begin; int end; int weight; gEdge():begin(0),end(0),weight(NULL){}; }gEdge; Graph G; void CreateGraph() { int VerterNum;char ver; cout<<"请输入顶点总数"<<endl; cin>>VerterNum; int i,j; memset(G.edge,0,sizeof(int)*50); cout<<"请输入图的顶点"<<endl; for(i=0;i<VerterNum;i++) { cin>>ver; G.ver[i]=ver; } cout<<"请输入有向图相对应的邻接矩阵"<<endl; int val=0;int edgenum=0; for(i=0;i<VerterNum;i++) for(j=0;j<VerterNum;j++) { cin>>val; G.edge[i][j]=val; } cout<<endl; //因为是有向图, for(i=0;i<VerterNum;i++) for(j=i;j<VerterNum;j++) { if(G.edge[i][j]!=0) { edgenum++;} } //只要其上三角就行 G.VerterNum=VerterNum;G.edgenum=edgenum; } //对数据边进行排序,产生生成图 gEdge *CreateEdge() { //边的数组 gEdge *p=new gEdge[G.edgenum]; int i,j,k=0; for(i=0;i<G.VerterNum;i++) for(j=i;j<G.VerterNum;j++) {//选择插入排序 if(G.edge[i][j]!=0) { p[k].begin=i; p[k].end=j; p[k].weight=G.edge[i][j]; k++; } } gEdge temp; for( i=0; i<G.edgenum-1; i++ ) //对边集数组进行选择排序 for( j=i+1; j<G.edgenum; j++ ) if( p[i].weight > p[j].weight ) { temp = p[i]; p[i] = p[j]; p[j] = temp; } return p; } int unionsearch(int x) //查找根结点+路径压缩 { return x == father[x] ? x : unionsearch(father[x]); } bool Union(int x,int y) { int root1,root2; root1=unionsearch(x); root2=unionsearch(y); if(root1==root2) { return false; } else { if(son[root1]>=son[root2]) { father[root2]=root1; son[root1]+=son[root2];//儿子接点数 } else{ father[root1]=root2; son[root2]+=son[root1]; } } return true; } void Krusual() { //得到Krusual排序生成矩阵信息; gEdge *p=CreateEdge(); int i ,j=0;int totalval=0; //没有环的矩阵 int *MST=new int[G.edgenum]; //使用Set中并操作,将原始是edgenum条离散的树整合成森林 //将其初始化,开始时候每个顶点的父节点都是自己,最后形成的森林(不成环) for(i=0;i<G.VerterNum;i++) { father[i]=i; son[i]=1; } int flag[MAxSize]; memset(flag,-1,sizeof(int)*MAxSize); for(i=0;i<G.edgenum;i++) { if(Union(p[i].begin,p[i].end)) { totalval+=p[i].weight; MST[j++]=i; flag[i]=1; cout<<G.ver[p[i].begin]<<"-->"<<G.ver[p[i].end]<<endl; } } if(j==G.VerterNum-1) { cout<<totalval<<endl; }else { cout<<"datat error"<<endl; } } int main() { CreateGraph(); Krusual(); return 0; }