#include < iostream .h > const int n=6; //图的顶点数const int e=10; //图的边数 n-1= < e < =n(n-1)/2 typedef int adjmatrix[n][n]; typedef struct{ //生成树的边结点 int fromvex,endvex; //边的起点与终点 int weight; //边上的权}TreeEdgeNode;typedef TreeEdgeNode edgesetT[n-1]; //这是不typedef TreeEdgeNode edgesetG[e];void Kruskal(edgesetG GE,edgesetT CT,int n)//利用克鲁斯卡尔算法求边集数组GE所示图的最小生成树,//树中每条边依次存于数组C中{ int i,j; adjmatrix s;//用二维数组s作为集合使用,其中每一行元素 //s[i][0]~s[i][n-1]用来表示一个集合,若s[i][t] ==1 //则表示v[t]顶点属于该集合,否则不属于s[i]集合 for(i =0;i<n;i++) { //初始化s集合,使每一个顶点分属于不同的集合 for(j =0;j<n;j++) if(i ==j) s[i][j] =1; else s[i][j] =0; }//循环执行结束后,使得v[i]顶点属于s[i]集合中 int k =1;//k表示待获取的最小生成树中的边数,初值为1 int d =0;//d表示GE中待扫描边元素的下标位置,初值为0 int m1,m2;//m1和m2用来分别记录一条边的两个顶点所在的集合的序号 while(k<n) {//进行n-1次循环,得到最小生成树中的n-1条边 /*for(i =0;i<n;i++) {//求出边GE[d]的两个顶点所在集合的序号m1和m2] for(j =0;j<n;j++) { if(GE[d].fromvex ==j&&s[i][j]==1)//找起点 m1 =i; if(GE[d].endvex ==j&&s[i][j]==1)//找终点 m2 =i; } }*/ //可以把上面的重for循环改良成如下的一重for循环 for(i =0;i<n;i++) { if(s[i][GE[d].fromvex] ==1)//找起点 m1 =i; if(s[i][GE[d].endvex] ==1)//找终点 m2 =i; } if(m1! =m2) { //若两集合序号不等,则表明GE[d]是生成树中的一条边, //应将它加入到数组C中 CT[k-1] =GE[d]; //cout<<"CT[<<k-1<<] =<<CT[k-1]. k++; for(j =0;j<n;j++) {//合并两个集合,并将另一个置为空集 s[m1][j] =s[m1][j]||s[m2][j]; s[m2][j] =0; } } d++;//d后移一个位置,以便扫描GE中的下一条边 }}void main(){ int i; edgesetG GE; edgesetT CT; cout<<"请按权值小到大输入边集:"<<endl; for(i =0;i<e;i++)//这是不妥的,因为不知道到底有多少边 { cin > >GE[i].fromvex>>GE[i].endvex>>GE[i].weight; } Kruskal(GE,CT,n); cout < <"最上生成树的边集为: "<<endl; for(i =0;i<n-1;i++) { cout<<CT[i].fromvex<<" "<<CT[i].endvex<<" "<<CT[i].weight<<endl; }}/*测试用例一:请按权值小到大输入边集:0 4 41 2 51 3 82 3 101 5 123 5 150 1 183 4 200 5 234 5 25最上生成树的边集为:0 4 41 2 51 3 81 5 120 1 18*/