最小生成樹(C語言, prim算法)

圖(來源:<<大話數據結構>>p250)

最小生成樹(C語言, prim算法)

#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]#
相關文章
相關標籤/搜索