最小生成樹Prim算法(鄰接矩陣和鄰接表)


  最小生成樹,普利姆算法.

簡述算法:

  先初始化一棵只有一個頂點的樹,以這一頂點開始,找到它的最小權值,將這條邊上的令一個頂點添加到樹中

  再從這棵樹中的所有頂點中找到一個最小權值(而且權值的另一頂點不屬於這棵樹)

  重復上一步.直到所有頂點並入樹中.

圖示:

注:以a點開始,最小權值為1,另一頂點是c,將c加入到最小生成樹中.樹中 a-c

在最小生成樹中的頂點找到一個權值最小且另一頂點不在樹中的,最小權值是4,另一個頂點是f,將f並入樹中, a-c-f

重復上一步驟,a-c-f-d, a-c-f-d-b, a-c-f-d-b-e.

鄰接矩陣的實現

我又構建了一個鄰接矩陣(prim_tree),將我們求出的最小生成樹寫入其中.

我們還需要一個visited數組,來確定一個頂點是否已被納入最小生成樹中.

1)初始化,visited數組,prim_tree節點信息,矩陣.1-11,41-55行

2)將一個頂點並入樹(prim_tree)中.以這個頂點開始,進行遍歷尋找最小權值.

  這里用了三層循環嵌套.

    i這一層的作用是遍歷圖的節點信息,我們要將所有節點都納入樹中.

    j這一層的作用是遍歷樹的節點信息.(我們是通過visited數組來確定一個節點是否屬於最小生成樹的,19行,if的作用)

    k這一層的作用是在j節點所在所在矩陣的行中找到最小權值.

 (注:j和k配合,找到樹中的最小權值(最小權值的另一個節點沒有被納入樹中,23行if的作用).j查找的節點信息的下標,但矩陣是正方形的,所以j既是節點信息的下標,又是該節點在矩陣中的列位置.而k則在j這一列查找最小權值.當j將樹遍歷一遍,這時會找到一個最小權值,這個最小權值的另一個頂點就是我們將要納入樹中的節點.)

3)將上面獲得的信息寫入樹中.(寫入時也要判斷該節點是否已被納入樹中.沒有納入樹中的節點才會將其納入樹中.)

 1 //最小生成樹prim算法
 2 static void init_prim(Graph * graph, Graph * prim_tree);
 3 void Prim(Graph * graph, Graph * prim_tree)
 4 {
 5     bool visited[graph->vertexs];
 6     int i, j, k, h;
 7     int power, power_j, power_k;
 8 
 9     for ( i = 0; i < graph->vertexs; i++ )
10         visited[i] = false;
11     init_prim(graph, prim_tree);
12 
13     visited[0] = true;
14     for ( i = 0; i < graph->vertexs; i++ )
15     {
16         power = MAX_VALUE;
17         for ( j = 0; j < graph->vertexs; j++ )
18         {
19             if ( visited[j] )
20             {
21                 for ( k = 0; k < graph->vertexs; k++ )
22                 {
23                     if ( power > graph->arcs[j][k] && !visited[k] )
24                     {
25                         power = graph->arcs[j][k];
26                         power_j = j;
27                         power_k = k;
28                     }
29                 }
30             }
31         }
32         //min power
33         if ( !visited[power_k] )
34         {
35             visited[power_k] = true;
36             prim_tree->arcs[power_j][power_k] = power;
37         }
38     }
39 }
40 
41 static void init_prim(Graph * graph, Graph * prim_tree)
42 {
43     int i, j;
44 
45     prim_tree->vertexs = graph->vertexs;
46     for ( i = 0; i < prim_tree->vertexs; i++ )//初始化節點
47         prim_tree->vertex[i] = graph->vertex[i];
48     for ( i = 0 ; i < prim_tree->vertexs; i++ )//初始化矩陣
49     {
50         for ( j = 0; j < prim_tree->vertexs; j++ )
51         {
52             prim_tree->arcs[i][j] = MAX_VALUE;
53         }
54     }
55 }

上述代碼適用於連通圖.

如果想運行這個程序,到http://www.cnblogs.com/ITgaozy/p/5187483.html找源碼,將上面的代碼粘到里面就可以了.

 

鄰接表的實現

算法和矩陣一樣,只是由於數據結構不同,在代碼上有些差別.

static void init_prim(Graph * graph, Graph * prim_tree);
void g_prim(Graph * graph, Graph * prim_tree)
{
    bool visited[graph->vertexs];
    int i, j, k;
    int power, pos;
    Arc_node * tmp;

    for ( i = 0; i < graph->vertexs; i++ )
        visited[i] = false;
    init_prim(graph, prim_tree);

    visited[0] = true;
    for ( i = 0; i < graph->vertexs; i++ )
    {
        power = INT_MAX;//limits.h
        for ( j = 0; j < graph->vertexs; j++ )
        {
            if ( visited[j] )
            {
                tmp = graph->adjlist[j].next;
                while ( tmp != NULL )
                {
                    if ( power > tmp->distance && !visited[tmp->pos] )
                    {
                        power = tmp->distance;
                        pos = tmp->pos;
                        k = j;
                    }
                    tmp = tmp->next;
                }
            }
        }
        if ( !visited[pos] )
        {
            if ( prim_tree->adjlist[k].next == NULL )
            {
                prim_tree->adjlist[k].next = make_node(pos, power);
            }
            else
            {
                tmp = prim_tree->adjlist[k].next;
                while ( tmp->next != NULL )
                    tmp = tmp->next;
                tmp->next = make_node(pos, power);
            }
            visited[pos] = true;
        }
    }
}

static void init_prim(Graph * graph, Graph * prim_tree)
{
    int i;

    for ( i = 0; i < graph->vertexs; i++ )
    {
        prim_tree->adjlist[i].info = graph->adjlist[i].info;
        prim_tree->adjlist[i].next = NULL;
    }
    prim_tree->vertexs = graph->vertexs;
}

到http://www.cnblogs.com/ITgaozy/p/5187526.html里找到源碼,將上述代碼粘到源碼中,就可以了.

由於本人水平有限,不足之處還望大家不吝指教.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM