克魯斯卡爾演算法的運用
阿新 • • 發佈:2020-12-20
程式碼展示
#define MAX 5000 #include"stdio.h" #include< stdlib.h > #pragma warning(disable : 4996) typedef struct { int fromvex; /*邊的起始點*/ int endvex; /*邊的終止點*/ int weight; /*邊的權值*/ }g; g tree[20] = { 0 }, GE[20] = { 0 }, TREE[20] = { 0 }, t; int edge[20][20], s[20][20] = { 0 }; int n, m; void kruskl() { int i, j, k, m1 = 0, m2 = 0, c; printf("請輸入頂點數和邊數:"); scanf("%d%d", &n, &m); for (i = 0; i < m; i++) /*輸入圖的所有邊*/ { printf("按起點,終點和權值依次輸入:"); scanf("%d%d%d", &GE[i].fromvex, &GE[i].endvex, &GE[i].weight); } for (i = 1; i < m - 1; i++) /*按邊的權值由小到大直接插入排序*/ { t = GE[i]; j = i - 1; while (j >= 0) { if (t.weight < GE[j].weight) { GE[j + 1] = GE[j]; j = j - 1; } else break; GE[j + 1] = t; } } printf("\n排序後的邊與對應的權值\n"); for (i = 0; i < m; i++) /*列印排序後的結果*/ printf("邊:%d->%d權值:%d\n", GE[i].fromvex, GE[i].endvex, GE[i].weight); for (i = 0; i < n; i++) /*初始化連通圖*/ { s[i][0] = 1; /*第0列表示一個連通分量中頂點數*/ s[i][1] = i; /*第1列後的列中均表示頂點的編號*/ } j = 0; /*表示圖G陣列的序號*/ i = 0; /*表示樹中邊的序號*/ while (i < n - 1) /*找n-1條邊形成最小生成樹*/ { k = 0; /*k表示s陣列的行號*/ while (k < n) /*判斷兩個頂點為同一連通分量否*/ { for (c = 1; c <= s[k][0]; c++) /*找所在的行號*/ { if (GE[j].fromvex == s[k][c]) m1 = k; /*起點行號*/ if (GE[j].endvex == s[k][c]) m2 = k; /*終點行號*/ } k++; } if (m1 != m2) /*不是同一連通分量將圖中一條邊合併到樹中*/ { TREE[i] = GE[j]; /*把圖中的邊放到樹中*/ i = i + 1; for (c = 1; c <= s[m2][0]; c++) /*修改連通分量*/ { s[m1][0] = s[m1][0] + 1; /*頂點個數加1*/ s[m1][s[m1][0]] = s[m2][c]; /*終點編號合併*/ } s[m2][0] = 0; /*合併後頂點數為0*/ } j++; } for (i = 0; i < n - 1; i++) { printf("生成樹的起點,終點權值"); printf("%d\t->%d\t%d\n", TREE[i].fromvex, TREE[i].endvex, TREE[i].weight); } } int main() { while (1) { int choice; system("cls"); printf("頂點請用從零開始的連續整數表示,權值請小於100"); printf("\n\n\n"); printf(" *****>主選單<*****\n\n\n"); printf(" 2----------克魯斯卡爾演算法\n"); printf(" 0----------退出程式\n"); printf("\n\n enter your choice :"); scanf("%d", &choice); if (choice < 0 || choice>3) return(0); switch (choice) { case 2: kruskl(); system("pause"); break; case 0: exit(0); } } }