我們在圖的定義中說過,帶有權值的圖就是網結構。一個連通圖的產生樹是一個極小的連通子圖,它含有圖中全部的頂 點,但只有足以構成一棵樹的n-1條邊。所謂的最小成本,就是n個頂點,用n-1條邊把一個連通圖串連起來,並且使得權值 的和最小。綜合以上兩個概念,我們可以得出:構造連通網的最小代價產生樹,即最小產生樹(Minimum Cost Spanning Tree)。
找連通圖的最小產生樹,經典的有兩種演算法,普裡姆演算法和克魯斯卡爾演算法,這裡介紹克裡姆演算法。
為了能夠講明白這個演算法,我們先構造網圖的鄰接矩陣,如圖7-6-3的右圖所示。
也就是說,現在我們已經有了 一個儲存結構為MGraph的MG(見《鄰接矩陣建立圖》)。MG有9個頂點,它的二維數組如右圖所示,數組中我們使用65535代 表無窮。
下面我們對著程式和每一步迴圈的圖示來看:
演算法代碼:
/* Prim演算法產生最小產生樹 */void MiniSpanTree_Prim(MGraph MG){ int min, i, j, k; int adjvex[MAXVEX];/* 儲存相關頂點下標 */ int lowcost[MAXVEX];/* 儲存相關頂點間邊的權值 */ lowcost[0] = 0;/* 初始化第一個權值為0,即v0加入產生樹 */ /* lowcost的值為0,在這裡就是此下標的頂點已經加入產生樹 */ adjvex[0] = 0;/* 初始化第一個頂點下標為0 */ cout << "最小產生樹的邊為:" << endl; for (i = 1; i < MG.numVertexes; i++) { lowcost[i] = MG.arc[0][i];/* 將v0頂點與之有邊的權值存入數組 */ adjvex[i] = 0;/* 初始化都為v0的下標 */ } for (i = 1; i < MG.numVertexes; i++) { min = INFINITY; /* 初始化最小權值為∞, */ j = 1; k = 0; while (j < MG.numVertexes)/* 迴圈全部頂點 */ { if (lowcost[j] != 0 && lowcost[j] < min)/* 如果權值不為0且權值小於min */ { min = lowcost[j];/* 則讓當前權值成為最小值 */ k = j;/* 將當前最小值的下標存入k */ } j++; } cout << "(" << adjvex[k] << ", " << k << ")" << " "; /* 列印當前頂點邊中權值最小的邊 */ lowcost[k] = 0;/* 將當前頂點的權值設定為0,表示此頂點已經完成任務 */ for (j = 1; j < MG.numVertexes; j++)/* 迴圈所有頂點 */ { /* 如果下標為k頂點各邊權值小於此前這些頂點未被加入產生樹權值 */ if (lowcost[j] != 0 && MG.arc[k][j] < lowcost[j]) { lowcost[j] = MG.arc[k][j];/* 將較小的權值存入lowcost相應位置 */ adjvex[j] = k;/* 將下標為k的頂點存入adjvex */ } } } cout << endl;}