最小生成树:Prim算法和Kruskal算法

样例(无向图):
在这里插入图片描述
1.Prim算法

#include <iostream>
#define MaxVertex 100
#define INF 100000
typedef int Vertex;
typedef class MatrixGraph* MGraph;
using namespace std;

class MatrixGraph
{
public:
	void Build(MGraph Graph);
	Vertex FindMin(MGraph Graph);
	void IniPrim(MGraph Graph,Vertex s);//初始化
	void Prim(MGraph Graph,Vertex s);
	void Output(MGraph Graph,Vertex s);
private:
	int Nv;
	int Ne;
	int G[MaxVertex][MaxVertex];
	int parent[MaxVertex];//并查集
	int dist[MaxVertex];//距离
	int sum;//权重和
	Vertex MST[MaxVertex];//最小生成树
};
//初始化
void MatrixGraph::Build(MGraph Graph)
{
	Vertex v1, v2;
	int weight;
	Graph->sum = 0;
	cout << "输入顶点数:";
	cin >> Graph->Nv;
	for (Vertex v = 1; v <= Graph->Nv; v++)
	{
		for (Vertex w = 1; w <= Graph->Nv; w++)//初始化图下标1开始
			Graph->G[v][w] = 0;
		Graph->dist[v] = INF;//初始化距离无穷大
		Graph->parent[v] = -1;//初始化并查集
	}
	cout << "输入边数:";
	cin >> Graph->Ne;
	cout << "输入边<v1,v2>和相应权重:"<<endl;
	for (Vertex v = 1; v <= Graph->Ne; v++)
	{
		cin >> v1 >> v2 >> weight;
		Graph->G[v1][v2] = weight;//无向边
		Graph->G[v2][v1] = weight;
	}
}
//prim算法前初始化
void MatrixGraph::IniPrim(MGraph Graph, Vertex s)
{
	Graph->MST[1] = s;//s为根节点
	Graph->dist[s] = 0;//树根节点距离初始化
	for (Vertex v = 1; v <= Graph->Nv; v++)//初始化s连接的所有边
	{
		if (Graph->G[s][v])
		{
			Graph->dist[v] = Graph->G[s][v];//更新v到根节点的距离
			Graph->parent[v] = s;//更新s作为父节点
		}
	}
}
//查找图中还存在的最小dist,返回顶点
Vertex MatrixGraph::FindMin(MGraph Graph)
{
	int min=INF;
	Vertex v=-1;
	for (Vertex i = 1; i <= Graph -> Nv; i++)
	{
		if (Graph->dist[i] && Graph->dist[i] < min)
		{
			min = Graph->dist[i];
			v = i;//记录最小顶点
		}
	}
	return v;
}
//prim算法
void MatrixGraph::Prim(MGraph Graph,Vertex s)
{
	int i = 1;
	IniPrim(Graph, s);
	while (1)
	{
		Vertex v = FindMin(Graph);
		if (v == -1)
			break;
		Graph->sum += Graph->dist[v];
		i++;
		Graph->MST[i] = v;//找到的顶点入树
		Graph->dist[v] = 0;//表示图中该顶点已删除
		for (Vertex w = 1; w <= Graph->Nv; w++)
		{
			if (Graph->G[v][w] && Graph->dist[w]&&Graph->dist[w] != 0 )//找到邻接点,路径存在且该点未被删除
			{
				if (Graph->G[v][w] < Graph->dist[w])//更新邻接点w信息
				{
					Graph->dist[w] = Graph->G[v][w];
					Graph->parent[w] = v;//v为父节点
				}
			}
		}
	}
	if (i < Graph->Nv)//收录进去的结点不到顶点个数
	{
		*Graph->MST = NULL;
	}
}
//输出
void MatrixGraph::Output(MGraph Graph,Vertex s)
{
	if (!*Graph->MST)
	{
		cout << "图不连通,最小生成树不存在";
	}
	else
	{
		cout << "被收录的顺序:"<<endl;
		for (int i = 1; i <= Graph->Nv; i++)
			cout << Graph->MST[i] << " ";
		cout << endl;
		cout << "权重和为:" << Graph->sum << endl;
		cout << "该生成树为:"<<endl;
		for (Vertex v = 1; v <= Graph->Nv; v++)
		{
			if (Graph->parent[v] == -1)
				Graph->parent[v] = s;
			cout << v << "--" << Graph->parent[v] << endl;
		}
	}
}
int main()
{
	Vertex s;
	MatrixGraph MG;
	MGraph Graph = new MatrixGraph;
	MG.Build(Graph);
	cout << "设置生成树的顶点:";
	cin >> s;
	MG.Prim(Graph, s);
	MG.Output(Graph,s);
	return 0;
}

运行:

在这里插入图片描述
2.Kruskal算法

#include <iostream>
#define MaxVertex 100
#define INF 100000
typedef class MGraph* Graph;
typedef int Vertex;
using namespace std;

class Edge
{
public:
	int v1, v2;
	int weight;
	int E[MaxVertex];//存边
};

class MGraph:public Edge
{
public:
	void Build(Graph Gra);
	int FindMin(Graph Gra);
	Vertex Find(Graph Gra, Vertex v);
	bool Union(Graph Gra, Vertex v, Vertex w);
	void Kruskal(Graph Gra);
	void Output(Graph Gra);
private:
	int G[MaxVertex][MaxVertex];
	int parent[MaxVertex];//并查集
	int MST[MaxVertex];//最小生成树
	int sum;//权重和
	int Nv;
	int Ne;
};
//初始化
void MGraph::Build(Graph Gra)
{
	Vertex v1, v2;
	int weight;
	Gra->sum = 0;
	cout << "输入顶点数:";
	cin >> Gra->Nv;
	for (Vertex v = 1; v <= Gra->Nv; v++)
	{
		for (Vertex w = 1; w <= Gra->Nv; w++)
			Gra->G[v][w] = 0;
		Gra->parent[v] = -1;
	}
	cout << "输入边数:";
	cin >> Gra->Ne;
	cout << "输入边<v1,v2>和相应权重:"<<endl;
	for (Vertex v = 1; v <= Gra->Ne; v++)
	{
		cin >> v1 >> v2 >> weight;
		Gra->weight = weight;
		Gra->E[v] = weight;
		Gra->G[v1][v2] = weight;//无向边
		Gra->G[v2][v1] = weight;
	}
}
//找出已知边里最小的,删除并返回最小
int MGraph::FindMin(Graph Gra)
{
	Vertex v, w;
	int min = INF;//无穷大
	for (v = 1; v <= Gra->Nv-1; v++)//无边图只扫描一个对角,这里取右上角
		for(w=v+1;w<=Gra->Nv;w++)
	{
		if (Gra->G[v][w] < min&&Gra->G[v][w]!=0)
		{
			min = Gra->G[v][w];
			Gra->v1 = v;
			Gra->v2 = w;
		}
	}
	return min;
}
//并查集查找操作
Vertex MGraph::Find(Graph Gra, Vertex v)
{
	if (Gra->parent[v] < 0)
		return v;
	else
		return Gra->parent[v] = Find(Gra, Gra->parent[v]);
}
//并查集并操作
bool MGraph::Union(Graph Gra, Vertex v, Vertex w)
{
	v = Find(Gra, v);
	w = Find(Gra, w);
	if (v!= w)
	{
		if (Gra->parent[v] < Gra->parent[w]) {
			Gra->parent[v] += Gra->parent[w];
			Gra->parent[w] = v;
		}
		else {
			Gra->parent[w] += Gra->parent[v];
			Gra->parent[v] = w;
		}
		return true;
	}
	else
		return false;

}
//Kruskal算法
void MGraph::Kruskal(Graph Gra)
{
	int i=0;//记录树结点
	int E;
	Gra->MST[MaxVertex] = {};//树开始为空
	while (i < Gra->Nv - 1 && FindMin(Gra) != INF)//树结点小于Nv-1,且还存在边
	{
		E = FindMin(Gra);
		Gra->G[Gra->v1][Gra->v2] = INF;//相当于删除
		if (Union(Gra,Gra->v1,Gra->v2))//不构成回路
		{
			i++;
			Gra->MST[i] = E;//入树
			Gra->sum += E;
		}
		else;//无视这条边

	}
	if (i < Gra->Nv - 1)
		*Gra->MST = NULL;
}
//输出
void MGraph::Output(Graph Gra)
{
	if (*Gra->MST == NULL)
	{
		cout << "该最小生成树不存在" << endl;
	}
	else
	{
		cout << "被收录顺序:"<<endl;
		for (int i = 1; i <= Gra->Nv - 1; i++)
			cout << Gra->MST[i] << " ";
		cout << endl;
		cout << "权重和:"<<Gra->sum<<endl;
		cout << "生成树:" << endl;
		for (Vertex v = 1; v <= Gra->Nv; v++)
		{
			
			cout << v << "--" << Gra->parent[v]<<endl;
		}
	}
}
int main()
{
	MGraph MG;
	Graph Gra = new MGraph;
	MG.Build(Gra);
	MG.Kruskal(Gra);
	MG.Output(Gra);
	delete Gra;
	return 0;
}

运行:

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值