图之 最小生成树 Prim算法

最小生成树之Prim算法

说明

Prim算法的时间复杂度为O(n^2),适合于求边稠密的网的最小生成树

代码

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;

#define INFINITY 65535  // 表示无穷大
#define maxSize 50
#define OK 1
typedef int VertexType;
typedef int EdgeType;

typedef struct
{
    VertexType vexs[maxSize];   //顶点坐标
    EdgeType arc[maxSize][maxSize];   //邻接矩阵定义,储存权值
    int n, e;
}MGraph;


//用邻接矩阵创建n个顶点,e个边,权值为w的无向图
void CreateMGraph(MGraph &G)
{
    int i, j;
    int v1, v2, w;   //v1 表示起点, v2表示终点 , w 表示权值
    cin >> G.n >> G.e;
    for (i = 1; i <= G.n; i++)
    {
        G.vexs[i] = i;
    }
    for (i = 1; i <= G.n; i++)
    {
        for (j = 1; j <= G.n; j++)
        {
            G.arc[i][j] = G.arc[j][i] = INFINITY; //初始化为无穷大
        }
    }
    for (i = 1; i < G.n; i++)
    {
        G.arc[i][i] = 0;  //自己到自己距离为0
    }
    for (i = 1; i <= G.e; i++)
    {
        cin >> v1 >> v2 >> w;
        G.arc[v1][v2] = G.arc[v2][v1] = w;
    }
}

void print(MGraph G)
{
    int i, j;
    for (i = 1; i <= G.n; i++)
    {
        for (j = 1; j <= G.n; j++)
        {
            printf("%d ", G.arc[i][j]);
        }
        printf("\n");
    }
}

//为了方便从下标为1的数组开始存储
void Prim(MGraph G,int v0)
{
    int min, i, j, k;
    int adjvex[maxSize];  //保存相关顶点下标
    int lowcost[maxSize];  //保存相关顶点间边的权值
    for (i = 1; i <= G.n; i++)
    {
        lowcost[i] = G.arc[v0][i];   //将v0顶点与之有边的权值存入数组
        adjvex[i] = v0;  // 初始化都为v0的下标
    }
    //v0已经加入最小生成树,故循环n-1次即可
    for (i = 1; i < G.n; i++)
    {
        min = INFINITY;
        k = 0;
        for (j = 1; j <= G.n; j++)
        {
            if (lowcost[j] != 0 && lowcost[j] < min)
            {
                min = lowcost[j];
                k = j;  //让当前最小值的下标存入k
            }
        }
        //打印当前顶点边中权值最小边,adjvex[k]存放的相当于起点
        printf("(%d %d)\n", adjvex[k], k); 
        //将当前结点的权值设置为0,表示此顶点已经完成任务
        lowcost[k] = 0; 
        for (j = 1; j <= G.n; j++)
        {
            //若下标为k顶点各边权值小于此前这些顶点未被加入生成树权值则更新lowcost
            if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
            {
                //将最小值存入lowcost
                lowcost[j] = G.arc[k][j];
                //将下标为k的顶点存入adjvex便于下一次输出最小边
                adjvex[j] = k;
            }
        }
    }
}

int main()
{
    //freopen("E:\input.txt", "r", stdin);
    MGraph G;
    CreateMGraph(G);
    print(G);
    Prim(G, 4); //将下标为1的点作为第一个点
    return 0;
}

Input

6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6

Output

0 6 1 5 65535 65535
6 0 5 65535 3 65535
1 5 0 5 6 4
5 65535 5 0 65535 2
65535 3 6 65535 0 6
65535 65535 4 2 6 65535
(4 6)
(6 3)
(3 1)
(3 2)
(2 5)

输入图例

输入图例

输出图例

输出图例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值