寻找最小生成树Prim和Kruskal

Prim算法又叫“加点法”,适用于稠密图。 

// Prim(最小生成树).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
using namespace std;

#define MAXNUM 255
#define INFINITY 65535
typedef char vexType;	//顶点类型
typedef int arcType;	//边的权值类型
/// <summary>
/// 无向网G
/// </summary>
typedef struct
{
	vexType vexs[MAXNUM];
	arcType arcs[MAXNUM][MAXNUM];
	int vexsNum, arcsNum;
}AMGraph;

/// <summary>
/// 存储路径信息
/// </summary>
typedef struct
{
	vexType head;
	vexType tail;
	arcType lowcost;
}Edge[MAXNUM];

/// <summary>
/// 找到图中的顶点
/// </summary>
/// <param name="G">无向图G</param>
/// <param name="v">顶点</param>
/// <returns>下标</returns>
int LocateVex(AMGraph G, vexType v)
{
	for (int i = 0; i < G.vexsNum; i++)
	{
		if (v == G.vexs[i])
			return i;
	}
	cout << "没有这个顶点!" << endl;
	return 0;
}

/// <summary>
/// 创建无向图的邻接矩阵
/// </summary>
/// <param name="G">无向图G</param>
void createGraph(AMGraph* G)
{
	vexType v1, v2;
	arcType w;
	int cnt = 1;
	cout << "请输入城市的规模和路径数目" << endl;
	cin >> G->vexsNum >> G->arcsNum;
	cout << "请输入城市" << endl;
	for (int i = 0; i < G->vexsNum; i++)
	{
		cin >> G->vexs[i];
	}
	//初始化邻接矩阵
	for (int i = 0; i < G->vexsNum; i++)
	{
		for (int j = 0; j < G->vexsNum; j++)
			G->arcs[i][j] = INFINITY;
	}
	//初始化完成
	cout << "请输入两个城市及路径权值" << endl;
	for (int i = 0; i < G->arcsNum; i++)
	{
		cin >> v1 >> v2 >> w;
		int m = LocateVex(*G, v1);
		int n = LocateVex(*G, v2);
		G->arcs[m][n] = w;
		G->arcs[n][m] = G->arcs[m][n];
	}
}

/// <summary>
/// 寻找与被标记的顶点有关的最小权值的边
/// </summary>
/// <param name="G">图</param>
/// <param name="visit">判断结点是否被访问的数组</param>
int findMin(AMGraph G,bool *visit,Edge closedge)
{
	int i, j, k, cnt = 0;
	int min = INFINITY;
	for (i = 0; i < G.vexsNum; i++)
	{
		if (true == visit[i])
		{
			for (j = 0; j < G.vexsNum; j++)
			{
				if (false == visit[j] && G.arcs[i][j] < min)
				{
					min = G.arcs[i][j];
					closedge[cnt].head = G.vexs[i];
					closedge[cnt].tail = G.vexs[j];
					k = j;
				}
			}
		}
	}
	visit[k] = true;
	closedge[cnt++].lowcost = min;
	//for (int i = 0; i < G.vexsNum; i++)
	//	cout << visit[i] << " ";
	cout << "    路径:";
	cout << closedge[cnt-1].head << "-" << closedge[cnt-1].tail << " $" << closedge[cnt-1].lowcost;
	cout << endl;
	return min;
}

/// <summary>
/// Prim
/// </summary>
/// <param name="G">图</param>
void MiniSpanTree_prim(AMGraph* G)
{
	int price = 0;
	Edge closedge;
	bool visited[MAXNUM];
	memset(visited, false, sizeof(visited));
	visited[0] = true;
	cout << "<-最低经济代价的通信网->" << endl;
	for (int i = 0; i < G->vexsNum - 1;i++)
	{
		price+=findMin(*G,visited,closedge);
	}
	cout << "总代价为:" << price;
}

int main(int argc, char* argv[])
{
	AMGraph G;
	//采用邻接矩阵表示无向网G
	createGraph(&G);
	//cout << "无向图的邻接矩阵为:" << endl;
	//for (int i = 0; i < G.vexsNum; i++)
	//{
	//	for (int j = 0; j < G.vexsNum; j++)
	//		cout << G.arcs[i][j] << "\t ";
	//	cout << endl;
	//}
	//根据邻接矩阵,利用Prim算法得到最小生成树
	MiniSpanTree_prim(&G);
	return 0;
}

Kruskal 又叫“加边法”,适用于稀疏图。

// Kruskal(最短路径).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
using namespace std;

#define MAXNUM 255
#define INFINITY 65535
typedef char vexType;	//顶点类型
typedef int arcType;	//边的权值类型
typedef struct
{
	vexType vexs[MAXNUM];
	arcType arcs[MAXNUM][MAXNUM];
	int vexsNum, arcsNum;
}AMGraph;

/// <summary>
/// 存储路径信息
/// </summary>
struct Edge
{
	vexType head;
	vexType tail;
	arcType lowcost;
};
/// <summary>
/// 快速排序
/// </summary>
/// <param name="a">第一个参数</param>
/// <param name="b">第二个参数</param>
/// <returns>比较结果</returns>
int cmp(const void* a, const void* b) {
	return ((struct Edge*)a)->lowcost - ((struct Edge*)b)->lowcost;
}
/// <summary>
/// 找到图中的顶点
/// </summary>
/// <param name="G">无向图G</param>
/// <param name="v">顶点</param>
/// <returns>下标</returns>
int LocateVex(AMGraph G, vexType v)
{
	for (int i = 0; i < G.vexsNum; i++)
	{
		if (v == G.vexs[i])
			return i;
	}
	cout << "没有这个顶点!" << endl;
	return 0;
}
/// <summary>
/// 创建无向图的邻接矩阵
/// </summary>
/// <param name="G">无向图G</param>
void createGraph(AMGraph* G,Edge closedge[])
{
	vexType v1, v2;
	arcType w;
	int cnt = 0;
	cout << "输入图的顶点数和边的条数" << endl;
	cin >> G->vexsNum >> G->arcsNum;
	cout << "输入顶点" << endl;
	for (int i = 0; i < G->vexsNum; i++)
	{
		cin >> G->vexs[i];
	}
	//初始化邻接矩阵
	for (int i = 0; i < G->vexsNum; i++)
	{
		for (int j = 0; j < G->vexsNum; j++)
			G->arcs[i][j] = INFINITY;
	}
	//初始化完成
	cout << "输入边的两个顶点和权值" << endl;
	for (int i = 0; i < G->arcsNum; i++)
	{
		cin >> v1 >> v2 >> w;
		int m = LocateVex(*G, v1);
		int n = LocateVex(*G, v2);
		G->arcs[m][n] = w;
		G->arcs[n][m] = G->arcs[m][n];

		closedge[i].head = G->vexs[m];
		closedge[i].tail = G->vexs[n];
		closedge[i].lowcost = w;
	}
}
/// <summary>
/// Kruskal
/// </summary>
/// <param name="G">无向图</param>
/// <param name="closedge">路径信息</param>
void MiniSpanTree_kruskal(AMGraph* G,Edge closedge[]) {
	int visit[MAXNUM];
	int price = 0;
	//初始化标记各不相同
	for (int i = 0; i < G->vexsNum; i++)
	{
		visit[i] = i;
	}
	qsort(closedge, G->arcsNum, sizeof(closedge[0]), cmp);
	cout << "<-最低经济代价的通信网->" << endl;
	for (int i = 0; i < G->arcsNum; i++)
	{
		int head = LocateVex(*G,closedge[i].head);
		int tail = LocateVex(*G, closedge[i].tail);
		if (visit[head] != visit[tail])
		{
			cout << closedge[i].head << "-" << closedge[i].tail<<" $"<<closedge[i].lowcost;
			price += closedge[i].lowcost;
			cout << endl;
			int temp = visit[head];
			for (int j = 0; j < G->vexsNum; j++)
			{
				if (visit[j] == temp)
				{
					visit[j] = visit[tail];
				}
			}
		}
	}
	cout << "总代价为:" << price;
}

int main(int argc, char* argv[])
{
	Edge closedge[MAXNUM];
	AMGraph G;
	createGraph(&G,closedge);
	
	MiniSpanTree_kruskal(&G, closedge);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

We尼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值