最小生成樹:我們把構造連通網的最小代價生成樹稱爲最小生成樹。
普里姆算法:
假設N = {V, E}是連通網,TE是N上最小生成樹中邊的集合。算法從U={u0}(u0∈V),TE={}開始。重複執行下述操作:在所有u∈U,v∈V-U的邊(u, v)∈E中找代價最小的邊(u0, v0)併入集合TE,同時v0併入U,直至U=V爲止。此時TE中必有n-1條邊,則T={V, TE}爲N的最小生成樹。此算法的時間複雜度是O(NxN)。
void MiniSpanTree_Prim(MGraph G)
{
int min, i, j, k;
int adjvex[MAXVEX];
int lowcost[MAXVEX];
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;
j = 1;k = 0;
while (j < G.numVertexes)
{
if (lowcost[j] != 0 && lowcost[j] < min)
{
min = lowcost[j];
k = j;
}
j++;
}
printf("(%d, %d) ", adjvex[k], k);
lowcost[k] = 0;
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;
}
}
}
}
克魯斯卡爾算法:
假設N={V, E}是連通網,則令最小生成樹的初始狀態爲只有n個頂點而無邊的非連通圖T={V, {}},圖中每個頂點自成一個連通分量。在E中選擇代價最小的邊,若該邊依附的頂點落在T中不同的連通分量上,則將此邊加入到T中,否則捨去該邊而選擇下一條代價最小的邊。依次類推,直至T中所以頂點都在同一連通分量爲止。此算法的時間複雜度是O(eloge)。
typedef struct
{
int begin;
int end;
int weight;
} Edge;
int Find(int *parent, int f)
{
while (parent[f] > 0)
f = parent[f];
return f;
}
void MiniSpanTree_Kruskal(MGraph G)
{
int i, n, m;
Edge edges[MAXEDGE];
int *parent[MAXVEX];
//此次省略將鄰接矩陣G轉化爲邊集數組edges並按權由小到大排序的代碼
for (i = 0; i < G.numVertexes; i++)
parent[i] = 0;
for (i = 0; i < G.numEdges; i++)
{
n = Find(parent, edges[i].begin);
m = Find(parent, edges[i].end);
if (n != m)
{
parent[n] = m;
printf ("(%d, %d) %d ", edges[i].begin, edges[i].end, edges[i].weight);
}
}
}