C/C++中的Prim算法代码实现

本文详细介绍了在C/C++中实现Prim算法的过程,包括算法的每一步骤和关键代码片段。作者强调了理解Prim算法的重要性,并提供了初始化、最小权值选择、更新未访问节点等步骤的详细解释。代码包括头文件、源文件和main函数,可用于测试。
摘要由CSDN通过智能技术生成

在网上找到很多Prim算法的相关博客,虽然很正确,但是感觉看不懂,代码也不能完成自己需要去做的作业。之前跟着一篇博客打过一次代码,但是我看不懂了(所以痛定思痛,以后一定写注释@_@),而且测试我之后写的代码,出现了内存错误。没办法。这里记下我写代码的过程。

找不到想要博客之后,决定自己想办法,把老师的ppt看了很多遍,但是ppt上的伪代码含糊不清,有用的只有Prim的手动计算过程(这个百度上搜的到,很容易看懂,但是换成程序对于我这种不听课的人就麻烦了)。因为伪代码对自己写程序有帮助,所以我决定先弄伪代码(伪代码比较水可以不看,不过我还是放在这里)。

1.初始化visit,再加一个cont变量,记录已经访问的点的数目
2.把开始的顶点在visit里标记为已读
3.把开始的点存入V中
4.初始化lowcost和adjvex(如下标k代表这个顶点k与adjvex[k]=j,意思是在lowcost集合中lowcost[k]代表的是k到j的权值)
(lowcost第一次初始化比较简单,直接把开始顶点那一行的值全部放进去就行了)
5.从lowcost里选一个最小的权值,然后用lowcostpoint记下来,这个点需要是没被访问的点
6.把lowcostpoint放进V中,visit标记一下
7.之后对lowcost再次进行操作,对于未访问的点,与访问过的点直接的权值进行比较,把每个未访问的点的最小权值用lowcost记下,顺便更换一下adjvex,把adjvex的值变为对应的点
8.继续操作5、6、7,直到所有点被访问
9.打印V(如果这里V不是数组,是树的话返回树)

第一步,根据Prim的计算过程,需要选取一个点作为开始访问的节点(网上很多直接从0开始,这样会省去很多步骤)

void GraphMatrix::Prim(int start_index)//在GraphMatrix类中的Prim函数

第二步,在函数中,需要一个判断节点是否被访问过的数组,数组下标对应的是顶点,推荐bool值,整型的话用0或1(废话 )。这些还不够,还需要一个储存访问的节点索引的数组(这个是为了打印结果到控制台用的),一个记录权值的数组lowcost和记录最小权值对应点lowcostpoint,附带一个min,好判断最小值。如果要返回的是一个树的话,还需要一个adjvex数组。剩下的其他变量带有注释,就不一一解释了。(m_size是这个图用二维数组储存,二维数组的大小)

	int lowcost[m_size]; //储存相关顶点的最小路径
    int lowcostpoint;//记录最小权值对应顶点
    int min;//方便之后选择最小权值
    
    bool visit[m_size];//判断节点有没有被访问
    for(int i = 0;i < m_size;i ++)//初始化访问数组
        visit[i] = false;
    int cont = 0;//计数
    int adjvex[m_size];//储存相关顶点
    int V[m_size];//储存访问顺序
    

    V[cont] = start_index;//添加开始节点
    visit[start_index-1] = true;
    cont++;

    int sum = 0;//总权值

注:visit这里的下标之所以减1,是因为在节点上,我是用1开始计数,而数组是从0开始的。所以需要减小1。之后的情况也一样。

第三步初始化lowcost和adjvex,因为刚开始只有一个节点被访问,所以直接把这个点所有的分量赋值给lowcost就行。

for(int i = 0;i < m_size;i ++)
{
   
    lowcost[i] = matrix[start_index-1][i];
    adjvex[i] = start_index - 1;
}

第四步,循环m_size-1次重复的操作,每一次都需要保证有一个节点,所以可能不适用于一些特殊情况。例如
在这里插入图片描述
代码片段:

for(int i = 1;i < m_size;i ++)//因为第一个点已经访问,为了防止用cont访问V越界,所以把i=0改成了i=1
{
   
    min = INF;

注:这里的INF定义如下

#define INF 65535

第六步,找到了最小的点,用之前申请的变量进行记录,把visit中对应的未访问(false)改为已访问(true),把这个节点记录在V中(所以cont的计数是在这用的)。另外,如果需要最小生成树的总权值,还需要把这个最小点的对应权值加上去。

        sum += lowcost[lowcostpoint];
        visit[lowcostpoint] = true;
        V[cont] = lowcostpoint + 1;
        cont++;

第七步,这里需要的东西有点多。主要是对lowcost的操作。在Prim算法中,很容易知道事把已经访问的节点看作一个集合(或者是点),然后再看和其他未访问顶点的连通分量。
两个集合都有未知个数的点,这里用了傻瓜方法,便于理解也便于操作。就是把visit遍历,对没有访问过的节点,把它与已经访问的节点的连通分量遍历,找到最小的,然后塞进lowcost里,已经访问过了其实操不操作已经无所谓了,但是这里还是把对应的值改为了INF。

        for(int j = 0;j < m_size;j ++)
        {
   
            if(!visit[j])
            {
   
                min = INF;
                for(int k = 0;k < m_size;k ++)//对于未访问的单个节点,寻找与被访问的节点权值最小的节点
                {
   
                    if(min > matrix[j][k] && visit[k])//需要的是已经访问的节点
                    {
   
                        min = matrix[j][k
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值