最小生成樹:普里姆算法編寫及演示

一,大致的遍歷過程圖解及過程講解

先從某一點開始尋找與其他邊連接最小的邊

1,如下圖(b)中,A與其它五點中C的距離最短,所以連接AC;

2,圖(c)將AC相比較,看誰與剩下點相連距離較短則替代,

      如AB=6,CB=5,所以取CB; AE,AF都不相連,而CE,CF都相連所以取AE,AF;

     此時比較AC與其它四點連接中距離最短的,所以連接CF;

3,圖(d)將ACF相比較,看誰與剩下點相連距離較短則其替代,

     如AD=5,FD=2,所以取FD;CE=6,FE=6,所以不管還用CE,F點B點無連接

     此時比較ACF與其它三點連接中距離最短的,所以連接FD;

4,。。。。。。(按照上面方法進行尋找最小)。

二,實現方法

這種方法除了構造鄰接矩陣所需的結構體和函數之外,新加入一個closedge結構體,數組中每一個頂點代表一個點到A的距離。

包含了對應頂點adjvex和權值lowcost。

        3代表頂點D

        eg:closedge[3]={A,5} 即代表3位置的頂點到A的距離爲5,即DA=5。

              此時若DC=3,則替換原來的A,變成closedge[3]={C,3};

 

第一步:先構造鄰接矩陣,並賦值,該過程類似於圖的鄰接矩陣儲存法類似。

第二步,先將遍歷開始頂點與其餘所有頂點的權賦值到closedge中,然後進行下面循環。

第三步:找到closedge數組中closedge[I].lowcost中最小的值所對應的位置n(即爲closedge[I].adjvex),然後將的權值lowcost變成0,即代表兩點連接。

第四步:將n與所有點連接的距離與closedge進行對比,如果比closedge小則對應替換。

然後再跳到第二步,進行下次循環,總共循環(頂點數-1)次。

此部分可能寫的不是特別好,但是需要講的都在最上面的圖解裏或者可以看下面運行截圖。

三,實現截圖

如下圖所示:每次遍歷出的closedge即爲每次替換後將要比較並取出最小值的。

四,代碼

#include<iostream>
using namespace std;

#define pointMax 100
#define cloEdge 100

typedef struct Node
{
    char adjvex;                       //在圖中的哪個頂點
    int lowcost;                       //權值
}closeedge[cloEdge];

struct AMgroup
{
    char VTchart[pointMax];                  //頂點表
    int AMchart[pointMax][pointMax];         //鄰接矩陣
    int point, vert;                         //點,邊
}; 

int AMlocate(AMgroup &A, char x)                        //找到某一頂點的位置
{
    for (int i = 0; i < A.point; i++)
    {
        if (A.VTchart[i] == x)
        {
            return i;
            break;
        }
    }
    cout << "error;";
    return -1;
}

void CreatAM(AMgroup &A)                      //構造鄰接矩陣
{
    cout << "輸入鄰接矩陣頂點數:";
    cin >> A.point;
    cout << "輸入鄰接矩陣邊數:";
    cin >> A.vert;
    getchar();

    char a[100];
    cout << "輸入點的信息:";
    gets_s(a);
    for (int i = 0; i < A.point; i++)             //依次輸入點的信息
    {
        A.VTchart[i] = a[i];
    }
    for (int i = 0; i < A.point; i++)              //初始換鄰接矩陣,邊的權值均設爲最大
    {
        for (int j = 0; j < A.point; j++)
        {
            A.AMchart[i][j] = -1;
        }
    }

    char v1, v2; int len;
    for (int i = 1; i <= A.vert; i++)               //構造鄰接矩陣
    {
        cout << "輸入第" << i << "條邊的兩個頂點以及權值:";
        cin >> v1 >> v2 >> len;
        int m, n;
        m = AMlocate(A, v1);
        n = AMlocate(A, v2);
        A.AMchart[m][n] = A.AMchart[n][m] = len;
    }
}

int k, j;

int Min(AMgroup &A,Node *closeedge)
{
    int a = 32767;
    int c;
    cout << endl;
    cout << "closeedge結構體數組遍歷:" << endl;
    for (int i = 0; i < j; i++)
    {
        cout<<A.VTchart[i]<<"      "<<closeedge[i].adjvex <<"    "<<closeedge[i].lowcost << endl;
        if (closeedge[i].lowcost < a  && closeedge[i].lowcost>0)           //如果closeedge[i].lowcost小於之前遍歷的最小值且未被遍歷
        {
            a = closeedge[i].lowcost;
            c = i;
        }
    }
    return c;
}

void MSTPrim(AMgroup &A, char m)                   //普利姆算法
{
    Node *closeedge = new Node;
    k = AMlocate(A, m);
    for (j = 0; j < A.point; j++)                   //賦值
    {
        closeedge[j] = { m, A.AMchart[k][j] };           //每個點到所求點的距離
    }
    closeedge[k].lowcost = 0;                          //自己到自己初始化爲0

    char u0, v0;
    for (int i = 1; i < A.point; i++)
    {
        k = Min(A,closeedge);                          //找到距離該點距離最短的位置
        u0 = closeedge[k].adjvex;                      //最小邊的一個頂點
        v0 = A.VTchart[k];                             //最小邊的另一個頂點
        cout <<k-1<<"點最小。"<<"本次遍歷邊:"<< u0 << "---" << v0 << endl;

        closeedge[k].lowcost = 0;                      //第K個頂點併入
        for (j = 0; j < A.point; j++)
        {
            if ((A.AMchart[k][j] < closeedge[j].lowcost && A.AMchart[k][j]>0)
                || (A.AMchart[k][j]>0 && closeedge[j].lowcost<0))             //新點周圍與遠點周圍進行判斷
            {
                closeedge[j] = { A.VTchart[k], A.AMchart[k][j] };
            }
        }
    }
}

int main()
{
    AMgroup *A = new AMgroup;
    CreatAM(*A);
    char m;
    cout << "輸入開始遍歷的值:";
    cin >> m;
    MSTPrim(*A, m);
    getchar();
    return 0;
}
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章