#include <stdio.h> #include <stdlib.h> #include <stdbool.h> /* * 鄰接矩陣, prim普里姆算法(屬貪婪算法),無向圖,最小生成樹 * 代碼實現<<大話數據結構>>p250 圖7-6-6,v0至v8分別用ABCDEFGHI代替(不過打印過程仍是用的下標) * 最終成生n-1條邊的樹,路徑權值和最小 */ #define MAX 9 #define INFINITY 65535 // 圖結構體 typedef struct { char vexs[MAX]; // 頂點的數組,頂點類型爲了簡單使用char int arc[MAX][MAX]; // 邊表二維數組,值爲權 int numVex; }GRAPH, *PGRAPH; void create(PGRAPH); void gprint(GRAPH); void prim(GRAPH); void prim(GRAPH graph) { int i, j, k, min; // 保存相關節點的數組(也可叫做父子(先後)關係,下標爲當前節點,值爲前一個節點,造成1條邊) int adjVex[MAX]; // 保存節點相關的邊的最小權值(這個是隨着程序不斷迭代而更新的) int lowcost[MAX]; // 循環處理前的初始化工做 adjVex[0] = 0; // 以第1個頂點爲開頭,直接加入v0節點 lowcost[0] = 0; // v0節點不須要再計算權值,標識爲0,0還有個意思表示該節點已經加入最小生成樹 // 使用v0節點相關的數據,初始化上面2個數組 for (i=0; i<graph.numVex; i++) { //先所有初始化爲0,表示全部節點的前1個節點都先爲v0 adjVex[i] = 0; // v0節點相關的邊權值加入數組,由於入口是v0節點,這些是目前能夠看到的相關的邊 lowcost[i] = graph.arc[0][i]; } /* * 開始循環處理,次數爲n-1,n爲節點數 */ // v0入口節點已經加入過數組不須要處理,因此從1開始 for (i=1; i<graph.numVex; i++) { // 每輪都須要計算當前未加入最小生成樹中的節點相關的最小權的邊 int min = INFINITY; // 先在lowcost數組中找出當前能夠看到的邊中,權值最小的那條邊 for (j=1; j<graph.numVex; j++) { if (lowcost[j] !=0 && lowcost[j] < min) { min = lowcost[j]; k = j; } } // 新找到的最小權值的邊的相關節點爲新查找根節點,標識爲0,放入最小生成樹 lowcost[k] = 0; printf("%d->%d\n", adjVex[k], k); //adjVex能夠知道相關節點先後關係 // 把符合條件的與新根節點(行)有關的邊、節點信息更新到數組,供下一輪查找 for (j=1; j<graph.numVex; j++) { if (lowcost[j] != 0 && graph.arc[k][j] < lowcost[j]) { lowcost[j] = graph.arc[k][j]; adjVex[j] = k; // 只要找到的更新其前節點爲k; } } } } void create(PGRAPH g) { int i, j; g->numVex = 9; // 建立頂點 g->vexs[0] = 'A'; g->vexs[1] = 'B'; g->vexs[2] = 'C'; g->vexs[3] = 'D'; g->vexs[4] = 'E'; g->vexs[5] = 'F'; g->vexs[6] = 'G'; g->vexs[7] = 'H'; g->vexs[8] = 'I'; // 初始化邊表 for (i=0; i<g->numVex; i++) { for (j=0; j<g->numVex; j++) { g->arc[i][j] = INFINITY; if (j == i) g->arc[i][j] = 0; //行列相等時表示自身,標識爲0 } } // 添加邊及權值 // A v0, B v1, C v2, D v3, E v4, F v5, G v6, H v7, I, v8 g->arc[0][1] = 10; g->arc[1][0] = 10; g->arc[0][5] = 11; g->arc[5][0] = 11; g->arc[1][2] = 18; g->arc[2][1] = 18; g->arc[1][8] = 12; g->arc[8][1] = 12; g->arc[1][6] = 16; g->arc[6][1] = 16; g->arc[2][8] = 8; g->arc[8][2] = 8; g->arc[2][3] = 22; g->arc[3][2] = 22; g->arc[3][8] = 21; g->arc[8][3] = 21; g->arc[3][6] = 24; g->arc[6][3] = 24; g->arc[3][7] = 16; g->arc[7][3] = 16; g->arc[3][4] = 20; g->arc[4][3] = 20; g->arc[4][7] = 7; g->arc[7][4] = 7; g->arc[4][5] = 26; g->arc[5][4] = 26; g->arc[5][6] = 17; g->arc[6][5] = 17; g->arc[6][7] = 19; g->arc[7][6] = 19; } void gprint(GRAPH graph) { int i, j; for (i=0; i<graph.numVex; i++) { for (j=0; j<graph.numVex; j++){ printf("%6d ", graph.arc[i][j]); } putchar('\n'); } } int main(void) { GRAPH graph; create(&graph); gprint(graph); prim(graph); return 0; }
output算法
[root@8be225462e66 c]# gcc prim.c && ./a.out 0 10 65535 65535 65535 11 65535 65535 65535 10 0 18 65535 65535 65535 16 65535 12 65535 18 0 22 65535 65535 65535 65535 8 65535 65535 22 0 20 65535 24 16 21 65535 65535 65535 20 0 26 65535 7 65535 11 65535 65535 65535 26 0 17 65535 65535 65535 16 65535 24 65535 17 0 19 65535 65535 65535 65535 16 7 65535 19 0 65535 65535 12 8 21 65535 65535 65535 65535 0 0->1 0->5 1->8 8->2 1->6 6->7 7->4 7->3 [root@8be225462e66 c]#