#include <iostream> #define INF 0x3fff #define MAXN 100 using namespace std; typedef struct { int s;//start结点 int e;//end结点 int w;//weight权值 }edge; edge e[MAXN*MAXN/2];//存储每一条边的数组 void insertsort(edge e[],int n)//直接插入排序 { int i,j; edge temp; for(i = 0 ; i < n ;i++) { temp = e[i]; j = i - 1; while(j >= 0 && temp.w < e[j].w) { e[j+1]= e[j]; j--; } e[j+1] = temp; } } void kruskal(int n,int mat[][MAXN])//Kruskal实现 { int i,j,k,m1,m2,sn1,sn2; edge e[MAXN*MAXN/2]; int vset[MAXN]; for(i = 0 ; i < n ; i++)//每个节点都初始化 vset[i] = i; k = 0; for(i = 0 ; i < n;i++) { for(j = 0 ; j < n;j++) { if(mat[i][j] != 0 && mat[i][j] != INF)//将邻接矩阵中的每一条边都加入到边权值的数组中 { e[k].s = i;e[k].e = j; e[k].w = mat[i][j]; k++; } } } insertsort(e,k);//对边的权值从大到小排序,这里采用直接插入排序,如果采用堆排序时间复杂度会减少 int cnt = 1 ;//记录加入到最小生成树的边的数量 k = 0; while(cnt < n) { m1 = e[k].s; m2 = e[k].e;//记录这条边的start , end 结点 sn1 = vset[m1]; sn2 = vset[m2];//看这两个结点属于哪一个set if(sn1 != sn2)//如果不等,说明这两个结点不在一个生成树中,合并 { printf("edge (%d,%d):%d is added!\n", e[k].s,e[k].e,e[k].w); cnt++; for(i = 0 ; i < n ; i++) { if(vset[i] == sn2)//把所有的原有的生成树的结点重新加入到新的生成树中 vset[i] = sn1; } } k++;//k为边的权值数组的Index } } int mat[MAXN][MAXN]; int main() { memset(mat,0,sizeof(mat)); int num; printf("please input vertex:"); scanf("%d",&num); int n; printf("input the number of edge:"); scanf("%d",&n); int t = n; while(t--) { int a,b,cost; scanf("%d %d %d",&a,&b,&cost); --a,--b; if(mat[a][b] == 0 && mat[b][a] == 0 || cost < mat[a][b] ) mat[a][b] = mat[b][a] = cost; } int i,j; for(i = 0 ; i < num;i++){ for(j = 0 ; j < num; j++) printf("%4d",mat[i][j]);printf("\n");} kruskal(num,mat); /* test data: 6 10 1 2 6 1 3 1 1 4 5 2 3 5 3 4 5 2 5 3 3 5 6 3 6 4 4 6 2 5 6 6 */ return 0; }