【算法】贪婪思想_图最小生成树_Prim算法

//
//  Prim_懒猫老师.cpp
//  §6Graph
//
//  Created by 郭宸羽 on 20/10/2022.
//

//
//  Prim_大话数据结构_p211.cpp
//  §6Graph
//
//  Created by 郭宸羽 on 19/10/2022.
//

#include <stdio.h>
#include <stdlib.h>
#define INF 65535
#define MAXVEX 9
struct MGraph{
    int Vertexesnum,numEdges;
    int arc_matrix[MAXVEX][MAXVEX];
};

//1.临接矩阵存储图的初始化———————————————————————————————————————————-————————————————————————————————————————————————
void InitialMGraph(MGraph&G)
{
    int i,j;
    G.Vertexesnum = 9; G.numEdges = 15;//1.1初始化图的顶点数和图的边数
    //1.2初始化图
    for(i = 0; i< G.Vertexesnum; i++)
    {
        for(j = 0; j< G.Vertexesnum;j++)
                G.arc_matrix[i][j] = INF;
    }
}
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————

//2.生成图的临接矩阵(临接矩阵赋值)——————————————————————————————————————————————————————————————————————————————————————
void CreateMGraph(MGraph*p_G)
{
    p_G->arc_matrix[0][1]=10;
    p_G->arc_matrix[0][5]=11;
    p_G->arc_matrix[1][2]=18;
    p_G->arc_matrix[1][8]=12;
    p_G->arc_matrix[1][6]=16;
    p_G->arc_matrix[2][8]=8;
    p_G->arc_matrix[2][3]=22;
    p_G->arc_matrix[3][8]=21;
    p_G->arc_matrix[3][6]=24;
    p_G->arc_matrix[3][7]=16;
    p_G->arc_matrix[3][4]=20;
    p_G->arc_matrix[4][7]=7;
    p_G->arc_matrix[4][5]=26;
    p_G->arc_matrix[5][6]=17;
    p_G->arc_matrix[6][7]=19;

    int i;int j;
    for(i = 0; i < p_G->Vertexesnum; i++)
    {
        for(j = i; j < p_G->Vertexesnum; j++)
        {
            p_G->arc_matrix[j][i] = p_G->arc_matrix[i][j];
        }
    }
}
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————


//3.Prim 生成最小生成树————————————————————————————————————————————————————————————————————————————————————————————————
void MinSpanTree_Prim(MGraph G,int root_v)
{
    int lowcost[G.Vertexesnum],adjvex[G.Vertexesnum];
    int i,j,sum = 0;
    int k;//k用于记录lowcost数组中新并入结点
    
    //3.1 Initial
    k = root_v;
    for(i= 0;i<G.Vertexesnum;i++)
    {
        lowcost[i] = G.arc_matrix[k][i];//1.Update(if(adjMatrix[k][j] < lowcast[j])⇒lowcast[j]=adjMatrix[k][j])
        adjvex[i] = k;//更新父亲列表 也可以写为: if(lowcost[i] == INF)->adjvex[i] = NOADJ; else->lowcost[i] = G.vertex[root_v]
    }
    lowcost[k] = 0;
    
    //3.2生成树
    for(i = 1;i<G.Vertexesnum;i++)
    {
        //3.2.1查找最小结点 标记并入树中
        //选择排序_遍历数组选最小值的算法 :int min = INF; for(int j = 0;j<num;j++){ if(min > lowcost[j]){ min = lowcost[j]; }
        int min = INF;
        for(j = 0;j<G.Vertexesnum;j++)
        {
            if(lowcost[j] != 0 && lowcost[j] < min)//❌更迭关系!min < lowcost[j]这条件条语句永远没法执行呀! 当前节点永远只能是0了!
            {
                min = lowcost[j];
                k = j;//目的是为了这个也就是找到新并入结点的下表
            }
        }
        sum += lowcost[k];
        lowcost[k] = 0;//双亲成立
        printf("(%d,%d) ",k,adjvex[k]);//打印的只是最新更新的
 
        //3.2.2 由于新结点并入树中 所以要更新图的的lowcost关系,更新结点的关联数组
        for(j = 0;j < G.Vertexesnum;j++)
        {
            if(lowcost[j] != 0 && G.arc_matrix[k][j] < lowcost[j] )
         //已经并入树的顶点不考虑   //连接图中在顶点新并入树之后距离变小的顶点
            {
                lowcost[j] = G.arc_matrix[k][j]; //更新————新顶点并入树之后到新顶点距离变小的边
                adjvex[j] = k;//改变预备新双亲(将新结点并入树导致距生成树的距离变小的顶点连接到变小的原因—————新并入的结点j上)
            }
        }
    }
    printf("sum weight of graph = %d\n",sum);
}

//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————

int main()
{
    MGraph G;
    InitialMGraph(G);
    CreateMGraph(&G);
    MinSpanTree_Prim(G,0);
                            
}
//1.两个数组 一个记录生成树结点间的关系(双亲表示法) 另一个记录每次生成树边的权值
//2.两次循环 第一次循环:初始化生成树(包括结点关系数组 和 边的权值)
//          第二次循环:生成树更新到完全生成树————外层大循环控制链接n-1个结点,内层小循环1:链接最小结点 2:更新边的权值信息

/*⚠️!为什么没有搞清楚? 1.∵lowcost数组的具体操作没有搞清楚,lowcost[i]表示以i为终点的边的最小权值✓,⚠️当lowcost[i]=0说明以i为终点的边的最小权值=0,也就是表示i点加入了MST
    2.mst[i]:表示对应lowcost[i]的起点,即说明边<mst[i],i>是MST的一条边,当mst[i]=0表示起点i加入MST
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值