使用邻接矩阵实现最小生成树Prim算法 (含注释)

 题目描述:

用邻接矩阵存储无向图,实现最小生成树Prim算法,图中边的权值为整型,顶点个数少于10个。

输入描述

首先输入图中顶点个数和边的条数;
再输入顶点的信息(字符型);
再输入各边及其权值。

输出描述

输出从编号为0的顶点开始的Prim算法最小生成树中的各边及其权值,每条边及其权值占一行。

输入样例

5 7
A B C D E
0 1 6
0 2 2
0 3 1
1 2 4
1 3 3
2 4 6
3 4 7

输出样例

A D 1
A C 2
D B 3
C E 6

第一种方法 

#include <iostream>
using namespace std;
#define MAX 20
#define INIFINTY 65535//理想无穷大 
typedef struct {
    
    int arc[MAX][MAX];//权重 
    char vertex[MAX];//顶点数据 
    int numVertexes, numEdges;//顶点大小和边长度 
}MGraph;
void CreateMGraph(MGraph * G,int n,int e){
    int i, j;
    G->numVertexes = n;  
    G->numEdges = e; 
    for (i = 0; i < G->numVertexes; i++) {  // 初始化图(自反的为零,非自反的为无穷大) 
        for (j = 0; j < G->numVertexes; j++) {
            if (i == j)//自反 
                G->arc[i][j] = 0;
            else//非自反 
                G->arc[i][j] = G->arc[j][i] = INIFINTY; //对称矩阵 
        }
    }
    for(int i = 0;i < n; i++)//存储顶点值 
    cin>>G->vertex[i];
    int i1,i2,i3;
    for(int i = 0; i < e; i++)//存储边顶点坐标和边的权重 
    {
    	cin>>i1>>i2>>i3;
    	 G->arc[i1][i2] = i3,G->arc[i2][i1]=i3;//对称 
	}
}
// Prime算法生成最小生成树
void MinPrim(MGraph G){
    int min,i,j,k;
    int adjvex[MAX]; // 保存相关顶点的下标
    int lowcost[MAX]; // 保存相关顶点间边的权值
    lowcost[0] = 0;  // 初始化第一个权值为0,即v0加入生成树
    adjvex[0] = 0; // 初始化第一个顶点下标为0
    
    for (i = 1; i < G.numVertexes; i++) {  // 循环除下标为0外的全部顶点
        lowcost[i] = G.arc[0][i];  // 将v0顶点与之右边的权值存入数组
        adjvex[i] = 0; // 初始化都为v0的下标
    }
    
    for (i = 1; i < G.numVertexes; i++) {
        min = INIFINTY; //初始化最小权值
        j = 1;
        k = 0;
        while (j < G.numVertexes) { // 循环全部顶点
            if (lowcost[j] != 0 && lowcost[j] < min) {
                min = lowcost[j];  // 让当前权值变为最小值
                k = j;  // 将当前最小值的下标存入k
            }
            j++;
        }
       cout<< G.vertex[adjvex[k]] <<" "<<G.vertex[k]<<" "<<lowcost[k]<<endl;  // 打印当前顶点和连接顶点权值最小的边及权值 
       	lowcost[k] = 0;             // 将当前顶点的权值设置为0,表示此顶点已经完成任务
        for (j = 1; j < G.numVertexes; j++) {  // 循环所有顶点
            if (lowcost[j]!= 0 && G.arc[k][j] < lowcost[j]) {  // 如果下标为k顶点各边权值小于当前这些顶点未被加入生成树权值
                lowcost[j] = G.arc[k][j]; // 将较小的权值存入lowcost相应的位置
                adjvex[j] = k;   // 将下标为k的顶点存入adjvex
            }
        }
    }
}
int main() {
    int n,e;
    cin>>n>>e;//输入顶点数和边数 
    MGraph G; 
    CreateMGraph(&G,n,e);
    MinPrim(G);
    return 0;
}

第二种(参考教材)

#include <iostream>
using namespace std;

const int MaxSize = 10;
const int INF = 32767;

class MGraph
{
public:
	MGraph(int n, int e);
	void Prim();
	
private:
	char vertex[MaxSize];
	int arc[MaxSize][MaxSize];
	int vertexNum, arcNum;
};

MGraph::MGraph(int n, int e)
{
	vertexNum=n, arcNum=e;
			for(int i=0;i<n;i++)
			for(int j=0;j<e;j++)
			{
				if(i==j)
				arc[i][j]=0;
				else
				arc[i][j]=arc[j][i]=INF;
			}
	for(int i=0;i<n;i++)
 	{
 		cin>>vertex[i];
	 }
	 int i1,j1,z1;
	 for(int i=0;i<e;i++)
	 {
	 	cin>>i1>>j1>>z1;
	 	arc[i1][j1]=z1,arc[j1][i1]=z1;
	 }

}

int MinEdge(int lowcost[], int vertexNum)
{	int min=INF;
	int j=0,k=1;
	while(j<vertexNum)
	{
		if(lowcost[j]!=0&&lowcost[j]<min)
		{
			min=lowcost[j];
			k=j;
		}
		j++;
	}
return k;
}

void MGraph::Prim()
{
	int k;
	int adjvex[MaxSize],lowcost[MaxSize];
	lowcost[0]=0,adjvex[0]=0;
	for(int i=1;i<vertexNum;i++)
	{
		lowcost[i]=arc[0][i];
		adjvex[i]=0;
	}
		lowcost[0]=0;
		for(int b=1;b<vertexNum;b++)
		{
			k=MinEdge(lowcost,vertexNum);
			cout<<vertex[adjvex[k]]<<" "<<vertex[k]<<" "<<arc[adjvex[k]][k]<<endl;
			lowcost[k]=0;
			for(int j=0;j<vertexNum;j++)
			{
				if(lowcost[j]!=0&&arc[j][k]<lowcost[j])
				{
					lowcost[j]=arc[k][j];
					adjvex[j]=k;
				}
			}
		}
}

int main()
{
	int n = 0;
	int e = 0;
	cin >> n >> e;
	MGraph MG(n, e);
	MG.Prim();
	return 0;
}

原始运行结果:

应网友要求,添加提示后:

#include <iostream>
using namespace std;
#define MAX 20
#define INIFINTY 65535//理想无穷大 
typedef struct {
    
    int arc[MAX][MAX];//权重 
    char vertex[MAX];//顶点数据 
    int numVertexes, numEdges;//顶点大小和边长度 
    
}MGraph;

void CreateMGraph(MGraph * G,int n,int e){
    int i, j;
    G->numVertexes = n;  
    G->numEdges = e; 
    for (i = 0; i < G->numVertexes; i++) {  // 初始化图(自反的为零,非自反的为无穷大) 
        for (j = 0; j < G->numVertexes; j++) {
            if (i == j)//自反 
                G->arc[i][j] = 0;
            else//非自反 
                G->arc[i][j] = G->arc[j][i] = INIFINTY; //对称矩阵 
        }
    }
    cout<<"请输入"<<n<<"个顶点值\n"; 
    for(int i = 0;i < n; i++)//存储顶点值 
    cin>>G->vertex[i];
    int i1,i2,i3;
    for(int i = 0; i < e; i++)//存储边顶点坐标和边的权重 
    {
    	cout<<"请输入"<<"第"<<i+1<<"对""存储边顶点坐标x,y和边的权重w:";
    	cin>>i1>>i2>>i3;
    	 G->arc[i1][i2] = i3,G->arc[i2][i1]=i3;//对称 
	}
}
// Prime算法生成最小生成树
void MinPrim(MGraph G){
    int min,i,j,k;
    int adjvex[MAX]; // 保存相关顶点的下标
    int lowcost[MAX]; // 保存相关顶点间边的权值
    lowcost[0] = 0;  // 初始化第一个权值为0,即v0加入生成树
    adjvex[0] = 0; // 初始化第一个顶点下标为0
    
    for (i = 1; i < G.numVertexes; i++) {  // 循环除下标为0外的全部顶点
        lowcost[i] = G.arc[0][i];  // 将v0顶点与之右边的权值存入数组
        adjvex[i] = 0; // 初始化都为v0的下标
    }
    
    cout<<"最小生成数即:\n"; 
    for (i = 1; i < G.numVertexes; i++) {
        min = INIFINTY; //初始化最小权值
        j = 1;
        k = 0;
        while (j < G.numVertexes) { // 循环全部顶点
            if (lowcost[j] != 0 && lowcost[j] < min) {
                min = lowcost[j];  // 让当前权值变为最小值
                k = j;  // 将当前最小值的下标存入k
            }
            j++;
        }
       cout<< G.vertex[adjvex[k]] <<"连"<<G.vertex[k]<<"权值:"<<lowcost[k]<<endl;  // 打印当前顶点和连接顶点权值最小的边及权值 
       	lowcost[k] = 0;             // 将当前顶点的权值设置为0,表示此顶点已经完成任务
        for (j = 1; j < G.numVertexes; j++) {  // 循环所有顶点
            if (lowcost[j]!= 0 && G.arc[k][j] < lowcost[j]) {  // 如果下标为k顶点各边权值小于当前这些顶点未被加入生成树权值
                lowcost[j] = G.arc[k][j]; // 将较小的权值存入lowcost相应的位置
                adjvex[j] = k;   // 将下标为k的顶点存入adjvex
            }
        }
    }
}
int main() {
    int n,e;
    cout<<"请输入顶点数和边数\n" ;
    cin>>n>>e;//输入顶点数和边数 
    MGraph G; 
    CreateMGraph(&G,n,e);
    MinPrim(G);
    return 0;
}

 提示运行结果:

 

  • 15
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿垚啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值