普利姆算法

普利姆算法

一:介绍:

(一):原理介绍

Prim算法构造最小生成树过程如下图所示:

​ 1、首先从图中任选一个顶点加入树T中,此时最小生成树T中就只含有一个顶点

​ 2、然后选择与当前最小生成树T中顶点集合距离最近的顶点,并将该顶点和相应的边加入最小生成树T中,每次操作树T中的顶点数量和边都加一。

​ 3、执行1,2两步,当图中的所有顶点都并入到T中,T就是最小生成树了。此时T中必有n-1条边
在这里插入图片描述

(二):算法思路介绍

​ 1、先初始化辅助数组,即从起始点到其他顶点的权值保存到数组中,并标志起始点

​ 2、循环执行以下操作(循环次数为图中顶点的数量减一,因为起始点不算)

​ (1)、定位数组中权值最小的权值,从而找到对应的下一个要加入的顶点。

​ (2)、在辅助数组中将新加入的顶点的权值置为0(自己到自己的距离为0)

​ (3)、跟新辅助数组,在新加入定点之后,集合T中的顶点到其他顶点的最小距离会变化,所以跟新新加入的顶点到其他顶点的距离,如果比原来的小,则跟新,否则不跟新。

二:代码

(一):结构

#ifndef DATASTRUCTURE_MST_H
#define DATASTRUCTURE_MST_H

#include <stdio.h>
#include "../Graph/Graph.h"
//#include "../Graph/Graph.c"

//生成树的类型定义
typedef struct {			
    VertexType adjvex;      //较早加入当前集合T的顶点(权值最小边的起始点)
    VRType lowcost;         //以该顶点为起始点的边的权值
}Edge;                      //辅助数组

typedef Edge closeEdge[MAX_VERTEX_NUM];     //创建一个辅助数组,表示已经加入到T中集合的顶点到其他顶点的最近距离

//在辅助数组中找到权值最小的边的数组下标
int Minimum(MGraph G,closeEdge close);

//普里母算法
void MinSpanTree_Prim(MGraph G,VertexType v);

#endif //DATASTRUCTURE_MST_H

(二):算法

#include "MST.h"

/**
 * 普利姆算法
 * @param G     无向网
 * @param v     开始顶点(随意)	初始为顶点1
 */
void MinSpanTree_Prim(MGraph G,VertexType v){
    int k = LocateVex(G,v);
    closeEdge close;		//辅助数组
    //初始化辅助数组,将与该起始点有关的所有边的信息:边的起始点和权值,初始化到辅助数组中
    //如初始顶点为1,那么有顶点1相连的有顶点2,3,4,则顶点1到2,3,4为其边上的权值,而与顶点5,6不相邻,所以为INFINITY
    //其中辅助数组的大小为图中顶点的数量,因此对应起始点与图中顶点的权值,即close[i].adjvex表示的是起始顶点,i对应的是顶点在
    //G中顶点数组的下标,所以可以通过i来找到顶点值
    for (int i = 0; i < G.vexnum; ++i) {
        if (i!=k){			
            close[i].adjvex = k;
            close[i].lowcost = G.arcs[k][i].adj;
        }
    }

    //因为起始点已经在最小生成树中了,所以需要将其辅助数组置0,或者因为从该点开始的,所以距离为0
    close[k].lowcost = 0;

    //选择下一个点,并更新辅助数组中的信息
    for (int i = 1; i < G.vexnum; ++i) {        //为什么从1开始,因为目前已经有一个在最小生成树中了
        k = Minimum(G,close);                   //找到权值最小的边所在数组的下标
        printf("v%d \t v%d\t",G.vexs[close[k].adjvex],G.vexs[k]);           //输出选择的路径
        close[k].lowcost = 0;                   //入树之后需要将权值设置为0

        //因为加入了一个顶点,那么辅助数组中的权值可能就会发生改变,所以,需要从新加入的顶点开始,比较其到其他邻接顶点的权值
        //如果小的就需要更新
        for (int j = 0; j < G.vexnum; ++j) {
            if (G.arcs[k][j].adj<close[j].lowcost){
                close[j].lowcost = G.arcs[k][j].adj;
                close[j].adjvex = k;

            }
        }
        printf("\n");
    }
}


//在辅助数组中找到权值最小的边的数组下标
int Minimum(MGraph G,closeEdge close){
    int min = INFINITY;			//为无向网,所以INFINTIY表示最大距离
    int index;
    for (int i = 0; i < G.vexnum; ++i) {
        if (close[i].lowcost>0&&close[i].lowcost<min){  //当权值为0的时候,说明顶点已经归到了最下生成树中了
            min = close[i].lowcost;
            index = i;
        }
    }
    return index;
}

/**
 * 确定顶点v在图中的位置
 * @param G
 * @param v		为顶点值
 * @return		如果在图的顶点数组中找到,则返回在数组中的下标,否则返回-1;
 */
int LocateVex(MGraph G,VertexType v){		
    for (int i = 0; i < G.vexnum; ++i) {
        if (v == G.vexs[i]){
            return i;
        }
    }
    return -1;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值