最小生成树(普里姆算法)

试实现普里姆最小生成树算法。

一、函数接口定义:

void Prim(AMGraph G, char u);

其中 G 是基于邻接矩阵存储表示的无向图,u表示起点

二、裁判测试程序样例:

#include <iostream>
#define MVNum 10
#define MaxInt 32767 
using namespace std;

struct edge{
    char adjvex;
    int lowcost;
}closedge[MVNum];

typedef struct{ 
    char vexs[MVNum];   
    int arcs[MVNum][MVNum]; 
    int vexnum,arcnum;
}AMGraph;
int LocateVex(AMGraph G , char v);//实现细节隐藏
int Min(AMGraph G);//实现细节隐藏
int CreateUDN(AMGraph &G);//实现细节隐藏

void Prim(AMGraph G, char u);

int main(){
    AMGraph G;
    CreateUDN(G);
    char u;
    cin >> u;
    Prim(G , u);
    return 0;
}

/* 请在这里填写答案 */

三、输入样例:

第1行输入结点数vexnum和边数arcnum。第2行输入vexnum个字符表示结点的值,接下来依次输入arcnum行,每行输入3个值,前两个字符表示结点,后一个数表示两个结点之间边的权值。最后一行输入一个字符表示最小生成树的起始结点。

7 9
0123456
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12
3 6 18
3 4 22
4 5 25
4 6 24
0

四、输出样例:

按最小生成树的生成顺序输出每条边。

0->5
5->4
4->3
3->2
2->1
1->6

全部代码如下:

#include <iostream>
#define MVNum 10
#define MaxInt 32767
using namespace std;

struct edge {
    char adjvex;
    int lowcost;
} closedge[MVNum];

typedef struct {
    char vexs[MVNum];
    int arcs[MVNum][MVNum];
    int vexnum, arcnum;
} AMGraph;

int LocateVex(AMGraph G, char v)
{
    // 实现细节隐藏
    // 这个函数用于定位顶点 v 在图 G 中的位置,返回顶点在 vexs 数组的下标
    // 可以使用 for 循环遍历 vexs 数组,找到与 v 匹配的顶点并返回下标
    for (int i = 0; i < G.vexnum; i++) {
        if (G.vexs[i] == v) {
            return i;
        }
    }
    return -1;  // 如果 v 不在 vexs 数组中,则返回 -1
}

int Min(AMGraph G)
{
    // 实现细节隐藏
    // 这个函数用于从 closedge 数组中选择权值最小的边并返回其下标
    // 可以使用循环遍历 closedge 数组,找到权值最小的边并返回其下标
    int minCost = MaxInt;
    int minIndex = -1;
    for (int i = 0; i < G.vexnum; i++) {
        if (closedge[i].lowcost < minCost && closedge[i].lowcost != 0) {
            minCost = closedge[i].lowcost;
            minIndex = i;
        }
    }
    return minIndex;
}

int CreateUDN(AMGraph& G)
{
    // 实现细节隐藏
    // 这个函数用于创建无向带权图 G
    // 可以根据需要设置图的顶点数和边数,并通过键盘输入顶点和边的信息
    // 可以使用嵌套循环来输入每条边的权值,如果两个顶点之间没有边,可以将对应位置的边权值设置为 MaxInt
    cout << "请输入顶点数和边数:";
    cin >> G.vexnum >> G.arcnum;

    cout << "请输入" << G.vexnum << "个顶点(用空格分隔):";
    for (int i = 0; i < G.vexnum; i++) {
        cin >> G.vexs[i];
    }

    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++) {
            G.arcs[i][j] = MaxInt;
        }
    }

    cout << "请输入" << G.arcnum << "个边的信息(起点 终点 权值):";
    for (int k = 0; k < G.arcnum; k++) {
        char v1, v2;
        int weight;
        cin >> v1 >> v2 >> weight;
        int i = LocateVex(G, v1);
        int j = LocateVex(G, v2);
        G.arcs[i][j] = weight;
        G.arcs[j][i] = weight; // 无向图,边是双向的,需要添加两条边
    }

    return 0;
}

void Prim(AMGraph G, char u)
{
    int uIndex = LocateVex(G, u);
    for (int i = 0; i < G.vexnum; i++) {
        if (i != uIndex) {
            closedge[i].adjvex = u;
            closedge[i].lowcost = G.arcs[uIndex][i];
        }
    }
    closedge[uIndex].lowcost = 0;

    for (int k = 1; k < G.vexnum; k++) {
        int minIndex = Min(G);
        cout << closedge[minIndex].adjvex << " -> " << G.vexs[minIndex] << endl;
        closedge[minIndex].lowcost = 0;

        for (int i = 0; i < G.vexnum; i++) {
            if (G.arcs[minIndex][i] < closedge[i].lowcost) {
                closedge[i].adjvex = G.vexs[minIndex];
                closedge[i].lowcost = G.arcs[minIndex][i];
            }
        }
    }
}

int main()
{
    AMGraph G;
    CreateUDN(G);
    char u;
    cout << "请输入起始顶点:";
    cin >> u;
    Prim(G, u);
    return 0;
}
posted @ 2023-06-20 15:05  YE-  阅读(55)  评论(0编辑  收藏  举报