最小生成树:普里姆算法编写及演示

一,大致的遍历过程图解及过程讲解

先从某一点开始寻找与其他边连接最小的边

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;
}
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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