Prim(普里姆算法)的C++实现,附源码及解释

 第一次写CSDN,不太熟悉。

#include<climits>//①

#include<vector>

//定义无穷大

const int INF = INT_MAX;

//Prim

void Prim(std::vector<std::vector<int>>&graph,int start){

    int V = graph.size();//顶点数量

    std::vector<bool>inMST(V,false);//判断是否在最小生成树中

    std::vector<int>key(V,INF);//key[i]表示从start到i的最小距离

    std::vector<int>parent(V,-1);//parent[i]表示生成树中i的父节点

    key[start] = 0;

    //有V个边所以遍历V-1次

    for(int count = 0;count < V-1;++count){

        //选择不在MST中且key值最小的点u

        int u = -1;       //②

        for(int v = 0;v<V;v++){

            if(!inMST[v]&&((u==-1)||key[v]<key[u])){

                u = v;

            }

        }

        //确定了预加入点,最后入MST

        inMST[u] = true;

       

        //每次加入一个新点,就要更新与之相邻顶点的key值

        for(int v = 0;v<V;v++){

            if(graph[u][v]!=0&&!inMST[v]&&graph[u][v]<key[v]){

                key[v] = graph[u][v];

                parent[v] = u;

            }

        }

    }

         // 打印最小生成树  

    for (int i = 0; i < V; ++i) {  

        if(i==start)//③

            continue;

        std::cout << parent[i] << " -- " << i << " == " << graph[parent[i]][i] << std::endl;  

    }

}

int main()

{

    std::vector<std::vector<int>> graph = {  

        {0, 2, 0, 6, 0},  

        {2, 0, 3, 8, 5},  

        {0, 3, 0, 0, 7},  

        {6, 8, 0, 0, 9},  

        {0, 5, 7, 9, 0}  

    };

    Prim(graph,3);

   

    return 0;

}

        其他的部分均容易理解,重点介绍一下代码中划线部分

①#include<climits>

        这个头文件中包含了一些常用的最大值的定义。

        INT_MAX : int 类型的最大值。
        INT_MIN : int 类型的最小值。
        UINT_MAX : unsigned int 类型的最大值。
        LONG_MAX : long int 类型的最大值。
        LONG_MIN : long int 类型的最小值。
        LLONG_MAX : long long int 类型的最大值。
        LLONG_MIN : long long int 类型的最小值。

②int u = -1;

目的:

        1.0 刚开始MST没有点,循环从v = 0开始。由于u = -1,满足if条件,毋庸置疑,一开始u一定是等于0的。那么之后呢,由于开始我们给所有key值均INT_MAX,而我们上面设置的key[start]=0,,会使得start点的key最小,当循环v = start那么就符key[start]<key[u],u则更新为start,且其为目前的最小,循环结束后,start点也就顺利地第一个进入了MST。

        2.0 外侧循环每进行一次,就会使u==-1,那么由判断里的u==-1必定会使一个顶点预加入MST(确定了点,但是还没进入MST),这样就可以实现每次添加点的效果。同时,这个点是按照顺序从前到后预加入的,但不一定是符合最小值的,那么内层循环接下来就会比较key值,就类似于冒泡排序,先确定一个key[u],再接下来去和其他的key[v]比较,如何有key[v]比key[u]小,那么预加入点u就更新为了v。最后循环结束,最小key的点一定找出来了,加入MST。       

 ③if(i==start) continue;

        因为start点是第一个进入MST中的,他就是根,所以parent[start] = -1;最后输出其没有意义。

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值