- #include<iostream>
- using namespace std;
- 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 4
- 1 2 5
- 1 3 8
- 2 3 10
- 1 5 12
- 3 5 15
- 0 1 18
- 3 4 20
- 0 5 23
- 4 5 25
- 最上生成树的边集为:
- 0 4 4
- 1 2 5
- 1 3 8
- 1 5 12
- 0 1 18
- */
Kruskal算法C++
最新推荐文章于 2024-06-27 09:22:55 发布