C/C++: Prim_MinSpanTree

/**
*
* Althor: Hacker Hao
* Create: 2023.12.04
*
*/
# include <bits/stdc++.h>
# define SIZE 20
# define NEWSIZE 20
# define MAXSIZE 100000000   //表示无限大
using namespace std;

//边的结构
typedef struct ArcNode 
{
	int adjvex;           //边的终点
	int value;           //权值
	struct ArcNode* nextarc;  //指向下一条边的指针
}ArcNode;

//顶点结构
typedef struct VNode 
{
	char data;
	ArcNode* firstarc;    //指向第一条与该顶点有关的边的指针
}VNode;

//图的结构
typedef struct
{
	VNode* VNode;
	int vexnum, arcnum;
	int size;
}Graph;

int* Adjvex;  //最小生成树中的顶点
int* Lowcost; //不在最小生成树中的各点到最小生成树中的点的边的最小权值 
int* Flag;    //标注该点是否已加入最小生成树

void Create(Graph& G)   //创建图(邻接表)
{
	cout << "请输入顶点和边的个数:";
	cin >> G.vexnum >> G.arcnum;

	G.VNode = (VNode*)malloc(SIZE * sizeof(VNode));
	G.size = SIZE;
	while (G.size <= G.vexnum) 
	{
		G.VNode = (VNode*)realloc(G.VNode, (G.size + NEWSIZE) * sizeof(VNode));
		G.size += NEWSIZE;
	}
	Adjvex = (int*)malloc((G.size + 10) * sizeof(int));
	Lowcost = (int*)malloc((G.size + 10) * sizeof(int));
	Flag = (int*)malloc((G.size + 10) * sizeof(int));
	cout << "请输入各顶点的名称:";
	for (int i = 1; i <= G.vexnum; i++) 
	{
		cin >> G.VNode[i].data;
		G.VNode[i].firstarc = NULL;  //邻接表初始化
	}

	cout << "请输入各边起点和终点的编号及权重:" << endl;
	int x, y, w;    //x:起始点    y:终点    w:权重
	ArcNode* p, * q;
	for (int i = 1; i <= G.arcnum; i++) 
	{
		cin >> x >> y >> w;
		p = (ArcNode*)malloc(sizeof(ArcNode)); //存放当前边的结点
		p->nextarc = NULL;
		p->adjvex = y;
		p->value = w;
		q = G.VNode[x].firstarc;

		if (q == NULL) 
		{
			G.VNode[x].firstarc = p;
		}
		else {
			while (q->nextarc != NULL) 
			{
				q = q->nextarc;
			}
			q->nextarc = p;
		}
		p = (ArcNode*)malloc(sizeof(ArcNode));
		p->nextarc = NULL;
		p->adjvex = x;
		p->value = w;
		q = G.VNode[y].firstarc;
		if (q == NULL) 
		{
			G.VNode[y].firstarc = p;
		}
		else {
			while (q->nextarc != NULL) 
			{
				q = q->nextarc;
			}
			q->nextarc = p;
		}
	}
}

void MinSpanTree_Prim(Graph& G, int v) //从顶点v出发求图的最小生成树
{
	for (int i = 1; i <= G.vexnum; i++) //初始化
	{  
		Adjvex[i] = v;
		Lowcost[i] = MAXSIZE;
		Flag[i] = 0;
	}
	Lowcost[v] = 0;
	Flag[v] = 1;             //把标记初始点
	cout << G.VNode[v].data << "->"; //输出初始点
	int num = 1;             //初始化最小生成树中的点的个数,即初始点
	ArcNode* p;
	while (num < G.vexnum) 
	{
		p = G.VNode[v].firstarc; //新加入树的点的邻接点
		while (p != NULL) 
		{
			if (!Flag[p->adjvex] && Lowcost[p->adjvex] > p->value) 
			{
				Lowcost[p->adjvex] = p->value;
				Adjvex[p->adjvex] = v;
			}
			p = p->nextarc;
		}
		int min = MAXSIZE;
		for (int i = 1; i <= G.vexnum; i++) 
		{
			if (!Flag[i] && Lowcost[i] < min) 
			{
				min = Lowcost[i];
				v = i;
			}
		}
		Flag[v] = 1;             //标记该点
		cout << G.VNode[v].data << "->"; //输出新加入树的点的值
		num++;                   //最小生成树中的点的个数++
	}
	cout << "EXIT" << endl;
}

int main()
{
	Graph G;
	Create(G);
	int sum = 0;
	cout << "最小生成树为:";
	MinSpanTree_Prim(G, 1);  //从第一个顶点出发

	for (int i = 1; i <= G.vexnum; i++) 
	{
		sum += Lowcost[i];         //求最小生成树的值
	}
	cout << "最小生成树的中两点间最大距离为:" << sum << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值