prim(普里姆)算法(c++,有图,邻接矩阵)

 

prim算法

![来自百度百科的无向图](https://i-blog.csdnimg.cn/blog_migrate/2971c51351b40f2e947729bde1ca5170.jpeg)

- [1 ]
在上图中我们事先选取v1作为起始点,将v1放入集合T中。选取集合T中的v1(按放入顺序),由图,它的邻接边中选取权值最小的的一条也就是(v1-->v2)将v2放入集合T中,并将v1,v2标记使以后的节点不能以它们作为终点。


- [ 2] 现在集合中有v1,v2。找到v1,v2的邻接边中权值最小的边也就是(v1-->v4)将v4放入集合T中,并将v4标记。


- [3 ] 按顺序遍历集合T,重复上述步骤。


- [4 ] ......


- [ 5] 最终使每个节点都在集合T中,结束操作。

过程如图所示:

  1.  
  2.  
  3.  

 

代码如图所示:

(这里使用邻接矩阵储存信息)

#include"bits/stdc++.h"
using namespace std;

#define MAX 24
#define INFINITE 201201

typedef char VertexType;
typedef int EdgeType;
typedef struct{//储存头节点信息 
    VertexType vertex;
}AdjMatrix[MAX],AdjMat;
typedef struct{//储存邻接矩阵信息 
    EdgeType map[MAX][MAX];//矩阵 
    AdjMatrix adjmatrix;
    int numsVertex,numsEdge;//节点和边的数量 
}MGraph;

void Initlize(MGraph *test){//初始化 
    for(int i=0;i<test->numsVertex;i++){
        for(int j=0;j<test->numsVertex;j++){
            if(i==j){
                test->map[i][j]=0;
            }
            else{
                test->map[i][j]=INFINITE;
            }
        }
    }
}
void CreateMat(MGraph *test){//输入边的信息,创建矩阵 
    for(int i=0;i<test->numsEdge;i++){
        char x,y;
        int weight,k,z,j=0;
        cin>>x>>y;
        while(test->adjmatrix[j].vertex!=x){
            j++;
        }
        k=j,j=0;        
        while(test->adjmatrix[j].vertex!=y){
            j++;
        }
        z=j;//j和节点对应 
        cin>>weight;
        test->map[k][z]=test->map[z][k]=weight;//赋权 
    }
}
void Prim(MGraph *test,bool visited[]){//普里姆算法 
    int min; 
    int min_x,min_y;// 最小权值对应边的信息 
    int i,j;
    queue <int> flag,temp;//flag相当于集合T ,temp用来找最小权值 
    flag.push(0);//将第一个节点放入flag中 
    visited[0]=true;//将第一个节点标记 
    while(flag.size()!=test->numsVertex){//当节点全部标记后结束 
        temp=flag;//将flag的信息传给temp 
        min=INFINITE;
        while(!temp.empty()){//依次拿出temp中存储的节点 
            
            i=temp.front();//i相当于节点对应的行 
            for(j=0;j<test->numsVertex;j++){//j对应列 
                if(test->map[i][j]>0&&min>test->map[i][j]&&!visited[j]){//找最小权值 
                    min=test->map[i][j];
                    min_x=i;
                    min_y=j;
                }
            }
            temp.pop();
            
        }
        visited[min_y]=true;
        flag.push(min_y);//将终节点放入flag中 
        test->map[min_y][min_x]=INFINITE;
        test->map[min_x][min_y]=INFINITE;//将查过的边赋值为INF 
        cout<<"("<<test->adjmatrix[min_x].vertex<<","<<test->adjmatrix[min_y].vertex<<")";
    }
    
}
int main(){
    MGraph test;
    bool visited[MAX]={false};//初始化visited 
    cin>>test.numsVertex>>test.numsEdge;
    for(int i=0;i<test.numsVertex;i++){
        cin>>test.adjmatrix[i].vertex;//输入头节点信息 
    }
    Initlize(&test);
    CreateMat(&test);
    Prim(&test,visited);

    return 0;
    
}

/*
Example:
6
10
ABCDEF
A B 6
A C 1
A D 5
B C 5
C D 5
B E 3
E C 6
C F 4
F D 2
E F 6

Matrix:
0       6       1       5       201201  201201
6       0       5       201201  3       201201
1       5       0       5       6       4
5       201201  5       0       201201  2
201201  3       6       201201  0       6
201201  201201  4       2       6       0
Result:
(A,C)(C,F)(F,D)(C,B)(B,E)
*/

第一次写博客,有不足请留言

>_<

date 2020/4/22 修改一处错误

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值