適用稠密圖,從頂點出發貪婪擴展。
#define MAXVEX 100
#define INFINITY 65535
void MiniSpanTree_Prim(MGraph G) {
int min, i, j, k;
int adjvex[MAXVEX]; // 最小邊的另一端頂點
int lowcost[MAXVEX]; // 最小邊權值
// 初始化:從 V0 開始
lowcost[0] = 0;
adjvex[0] = 0;
for (i = 1; i < G.numVertexes; i++) {
lowcost[i] = G.arc[0][i];
adjvex[i] = 0;
}
for (i = 1; i < G.numVertexes; i++) {
min = INFINITY;
// 尋找最小權值邊
for (j = 1; j < G.numVertexes; j++)
if (lowcost[j] != 0 && lowcost[j] < min) {
min = lowcost[j];
k = j;
}
printf("邊 (%d, %d) 權值: %d\n", adjvex[k], k, min);
lowcost[k] = 0; // 標記已加入 U
// 更新 lowcost
for (j = 1; j < G.numVertexes; j++)
if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j]) {
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
}
}
適用稀疏圖,從邊出發貪婪選擇。
int parent[MAXVEX];
int Find(int x) {
while (parent[x] >= 0) x = parent[x];
return x;
}
void Union(int x, int y) {
int rx = Find(x), ry = Find(y);
if (rx != ry) parent[rx] = ry;
}
typedef struct {
int begin, end;
int weight;
} Edge;
void MiniSpanTree_Kruskal(MGraph G) {
Edge edges[MAXVEX * MAXVEX];
int edgeCount = 0;
// 收集所有邊 (無向圖只取上三角)
for (int i = 0; i < G.numVertexes; i++)
for (int j = i + 1; j < G.numVertexes; j++)
if (G.arc[i][j] != INFINITY) {
edges[edgeCount++] = {i, j, G.arc[i][j]};
}
// 排序 (可用 qsort)
qsort(edges, edgeCount, sizeof(Edge), cmpWeight);
// 初始化並查集
for (int i = 0; i < G.numVertexes; i++) parent[i] = -1;
int selected = 0;
for (int i = 0; i < edgeCount && selected < G.numVertexes - 1; i++) {
int u = Find(edges[i].begin);
int v = Find(edges[i].end);
if (u != v) {
Union(u, v);
printf("選擇邊 (%d, %d) 權值: %d\n", edges[i].begin, edges[i].end, edges[i].weight);
selected++;
}
}
}
| 特性 | Prim | Kruskal |
|---|---|---|
| 策略 | 頂點擴展 | 邊選擇 |
| 資料結構 | 鄰接矩陣/表 + 最小權陣列 | 邊陣列 + 排序 + 並查集 |
| 時間複雜度 | O(n²) 矩陣 / O(e log n) 堆優化 | O(e log e) 排序主導 |
| 適用圖型 | 稠密圖 (e ≈ n²) | 稀疏圖 (e ≪ n²) |
| 實作難度 | 中等 | 需並查集、排序 |
參考文章中的圖示範例:Kruskal 依序選擇權值 5, 5, 6, 7, 7, 9 的邊,跳過會成環的 8, 8, 8,最終構成 MST。完美展現貪婪策略「局部最優 → 整體最優」的特性。