数据结构——Prim算法

基本思想:(加点)
设G=(V, E)是具有n个顶点的连通网,
T=(U, TE)是G的最小生成树,
T的初始状态为U={u0}(u0∈V),TE={ },
重复执行下述操作:
在所有u∈U,v∈V-U的边中找一条代价最小的边(u, v)并入集合TE,同时v并入U,直至U=V。

伪代码:

算法:Prim
输入:无向连通网G=(V,E)
输出:最小生成树T=(U,TE)
1. 初始化两个辅助数组lowcost=arc[0][i]和adjvex=0(0是始点)2. 输出顶点u0,将顶点u0加入集合U中;
3. 重复执行下列操作n-13.1 在lowcost中选取最短边(lowcost[k]),取对应的顶点序号k;
   3.2 输出顶点k和对应的权值;
   3.3 将顶点k加入集合U中(lowcost[k]=0);
   3.4 调整数组lowcost和adjvex;

代码实现:

#include<iostream>
using namespace std;

const int Max=10;//图中最多顶点个数
int visited[Max]={0};//全局数组变量visited初始化

class MGraph{
    char vertex[Max];//存放顶点的数组
    int edge[Max][Max];//存放边的数组
    int vertexNum,edgeNum;//顶点数和边数
    int MinEdge(int r[],int n);
public:
    MGraph(char a[],int n,int e);//构造函数,建立具有n个顶点e条边的图
    ~MGraph(){};//析构函数为空
    void DFT(int v);//深度优先遍历
    void BFT(int v);//广度优先遍历
    void prim(int v);//prim算法找最小生成树
};
//无权值图的构造函数
/*MGraph::MGraph(char a[],int n,int e){
    int i,j,k;//i j边依附的顶点编号
    int w;//权值
    vertexNum=n;
    edgeNum=e;
    for(i=0;i<vertexNum;i++)
        vertex[i]=a[i];
    for(i=0;i<vertexNum;i++)
        for(j=0;j<vertexNum;j++)
            edge[i][j]=0;
        for(k=0;k<edgeNum;k++)
        {
            cin>>i>>j;//输入边依附的两个顶点编号
            edge[i][j]=1;edge[j][i]=1;//置有边标志
        }
}*/
//有权值图的构造函数
/*MGraph::MGraph(char a[],int n,int e){
    int i,j,k;//i j边依附的顶点编号
    int w;//权值
    vertexNum=n;
    edgeNum=e;
    for(i=0;i<vertexNum;i++)
        vertex[i]=a[i];
    for(i=0;i<vertexNum;i++)
        for(j=0;j<vertexNum;j++)
            if(i==j)
                edge[i][j]=0;
            else
                edge[i][j]=100;//边上权的最大值100
        for(k=0;k<edgeNum;k++)
        {
            cin>>i>>j>>w;//输入边依附的两个顶点编号,权值
            edge[i][j]=w;edge[j][i]=w;//置有边标志
        }
}*/

MGraph::MGraph(char a[],int n,int e){
    int i,j,k;//i j边依附的顶点编号
    int w;//权值
    vertexNum=n;
    edgeNum=e;
    for(i=0;i<vertexNum;i++)//存储顶点
        vertex[i]=a[i];
    for(i=0;i<vertexNum;i++)//初始化邻接矩阵
    {
        for(j=0;j<vertexNum;j++)
        {
            cin>>w;//输入权值
            edge[i][j]=w;
            edge[j][i]=w;
        }
    }
}

int MGraph::MinEdge(int r[],int n)
{
    int min=100;//仅记载最小值下标会有bug
    int j=0;
    for(int i=1;i<n;i++)
    {
        if(r[i]!=0&&r[i]<min)
        {
            min=r[i];
            j=i;
        }
    }
    return j;
}

void MGraph::DFT(int v)
{
    cout<<vertex[v];visited[v]=1;
    for(int j=0;j<vertexNum;j++)
        if(edge[v][j]==1&&visited[j]==0)
            DFT(j);
}

void MGraph::BFT(int v)
{
    int w,j,Q[Max];
    int front=-1,rear=-1;
    cout<<vertex[v];
    visited[v]=1;
    Q[++rear]=v;
    while(front!=rear)
    {
        w=Q[++front];
        for(j=0;j<vertexNum;j++)
            if(edge[w][j]==1&&visited[j]==0)
            {
                cout<<vertex[j];
                visited[j]=1;
                Q[++rear]=j;
            }
    }
}

void MGraph::prim(int v)//从顶点v出发
{
    int i,j,k;
    int adjvex[Max],lowcost[Max];
    for(i=0;i<vertexNum;i++)//初始化辅助数组
    {
        lowcost[i]=edge[v][i];
        adjvex[i]=v;
    }
    lowcost[v]=0;//将顶点v加入到集合
    for(k=1;k<vertexNum;k++)//迭代n-1次
    {
        j=MinEdge(lowcost,vertexNum);//寻找最短边的邻接点j
        cout<<lowcost[j]<<" ";
        lowcost[j]=0;//顶点j加入到集合
        for(i=0;i<vertexNum;i++)//调整辅助数组
            if(edge[i][j]<lowcost[i])
            {
                lowcost[i]=edge[i][j];
                adjvex[i]=j;
            }
    }
}

/*int main()
{
    int i;
    char ch[]={'A','B','C','D','E','F'};
    MGraph MG(ch,6,9);
    for(i=0;i<Max;i++)
        visited[i]=0;
    cout<<"深度:";
    MG.DFT(0);
    for(i=0;i<Max;i++)
        visited[i]=0;
    cout<<"广度:";
    MG.BFT(0);
    MG.prim(0);
    return 0;
测试数据,输入边依次为 
0 1 34
0 2 46
0 5 19
1 4 12
2 3 17
2 5 25
3 4 38
3 5 25
4 5 26
}*/
int main()
{
    int n,m;
    cin>>n>>m;
    char ch[n];
    for(int i=0;i<n;i++)
    ch[i]='A'+i;
    MGraph MG(ch,n,m);
    MG.prim(0);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值