最小生成树 7.9源码

#include <bits/stdc++.h>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;
typedef int ElemType;

#define INFINITY 65535    //最大值∞
#define MAX_VERTEX_NUM 20 //最大顶点个数

typedef int Status;
typedef int VRType;
typedef char InfoType;
typedef int VertexType;
typedef enum
{
    DG,
    DN,
    UDG,
    UDN
} GraphKind; //{有向图,有向网,无向图,无向网}

typedef struct ArcCell
{
    VRType adj;     //VRType 是顶点关系类型。对无权图,用0或1表示相邻否;对带权图,则为权值类型
    InfoType *info; //该弧相关信息的指针
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
    VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
    AdjMatrix arcs;                  //邻接矩阵
    int vexnum, arcnum;              //图的当前顶点数和弧数
    GraphKind kind;                  //图的种类标志
} MGraph;

typedef struct
{
    VertexType adjvex;
    VRType lowcost;
} CLOSEDGE;

/*******************************声明部分****************************************/
Status CreateUDN(MGraph *G);
//构造无向网
int LocateVex(MGraph G, VertexType v);
//确定v在G中的位置
int minimum(CLOSEDGE closedge[], int n);
//返回最小连接的顶点序号
void MiniSpanTree_PRIM(MGraph G, VertexType u);
//用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
//记录从顶点集U到V-U的代价最小的边的辅助数组定义
/*******************************函数部分****************************************/
Status CreateUDN(MGraph *G)
{
    printf("\n构造无向网\n");
    int i, j, k;       //i,j,k用于计数
    int w;             //权重
    VertexType v1, v2; //弧头,弧尾

    printf("请输入顶点个数:");
    scanf("%d", &(*G).vexnum);
    printf("请输入弧个数:");
    scanf("%d", &(*G).arcnum);
    //假定该图不含其他信息
    int IncInfo = 0;

    for (i = 0; i < (*G).vexnum; i++)
    { //构造顶点向量
        printf("请输入G.vexs[%d] = ", i);
        scanf("%d", &(*G).vexs[i]);
    } //for

    for (i = 0; i < (*G).vexnum; i++) //初始化邻接矩阵
        for (j = 0; j < (*G).vexnum; j++)
        {
            (*G).arcs[i][j].adj = INFINITY; //无向网
            (*G).arcs[i][j].info = NULL;
        }

    for (k = 0; k < (*G).arcnum; k++)
    {                                   //构造邻接矩阵
        printf("请输入弧头(初始点):"); //输入一条弧的始点和终点
        scanf("%d", &v1);
        printf("请输入弧尾(终端点):");
        scanf("%d", &v2);
        printf("请输入权重:");
        scanf("%d", &w);

        i = LocateVex(*G, v1);
        j = LocateVex(*G, v2);

        if (i >= 0 && j >= 0)
            (*G).arcs[i][j].adj = (*G).arcs[j][i].adj = w; //置<v1,v2>的对称弧<v2,v1>

        //不再输入该弧含有的相关信息
    }
    (*G).kind = UDN;
    return OK;
}

int LocateVex(MGraph G, VertexType v)
{
    int ct;
    for (ct = 0; ct < G.vexnum; ct++)
        if (G.vexs[ct] == v)
            return ct;
    return -1;
}

int minimum(CLOSEDGE closedge[], int n)
{
    int i = 0, j, min, k;
    while (!closedge[i].lowcost)
        i++;
    min = closedge[i].lowcost;
    k = i;
    for (j = 1; j < n; j++)
        if (closedge[j].lowcost)
            if (min > closedge[j].lowcost)
            {
                min = closedge[j].lowcost;
                k = j;
            } //if
    return k;
}

void MiniSpanTree_PRIM(MGraph G, VertexType u)
{
    CLOSEDGE closedge[G.vexnum + 1];
    int k, j, i;

    k = LocateVex(G, u);
    for (j = 0; j < G.vexnum; ++j)
        if (j != k)
        { //辅助数组初始化
            closedge[j].adjvex = u;
            closedge[j].lowcost = G.arcs[k][j].adj;
        } //if

    closedge[k].lowcost = 0; //初始,U = {u}
    for (i = 1; i < G.vexnum; ++i)
    { //选择其余G.vexnum-1个顶点

        k = minimum(closedge, G.vexnum);                    //求出T的下一个结点:第k个顶点
        printf("(%d,%d)\n", closedge[k].adjvex, G.vexs[k]); //输出生成树的边

        closedge[k].lowcost = 0; //第k顶点并入U集

        for (j = 0; j < G.vexnum; ++j)
        {
            if (G.arcs[k][j].adj < closedge[j].lowcost)
            { //新顶点并入U集后重新选择最小边
                closedge[j].adjvex = G.vexs[k];
                closedge[j].lowcost = G.arcs[k][j].adj;
            } //if
        }     //for
    }         //for
}

/*******************************主函数部分**************************************/

int main()
{
    MGraph G;
    printf("P174 图7.16(a)\n");
    CreateUDN(&G);
    printf("\n输出生成树上的5条边为:\n");
    MiniSpanTree_PRIM(G, 1);
    return 0;
}

posted @ 2022-11-20 00:31  降蓝  阅读(27)  评论(0编辑  收藏  举报