数据结构:最小生成树的算法实现

题目:

利用普里姆(Prim)算法或克鲁斯卡尔(Kruskal)算法求上图的最小生成树

思路:

(1) 普利斯的邻接矩阵算法:从已选顶点所关联的未选边中找出权重最小的边,并且生成树不存在环。其中,已选顶点是构成最小生成树的结点,未选边是不属于生成树中的边。
(2) A.将边按权值从小到大的顺序添加到新图中,保证添加的过程中不会形成环
B.重复上一步直到连接所有顶点,此时就生成了最小生成树。这是一种贪心策略。

代码块:

#include "pch.h"
#include <iostream>
#include<queue>
using namespace std;
#define MVNum 100
#define INFINITY 65535
typedef char VerTexType;//顶点数据类型设置为字符
typedef int ArcType;//边的权值为整型
typedef int OtherInfo;
bool visited[MVNum] = { false };
/*********普里姆算法***********/
struct AMGraph {
	VerTexType vexs[MVNum];//顶点表
	ArcType arcs[MVNum][MVNum];//邻接矩阵
	int vexnum;//顶点数量
	int	arcnum;//边数量
};
struct Closedge {//辅助数组结构
	ArcType lowcost;//权值
	VerTexType adjvex;//顶点
};
int Locatevex(AMGraph G, VerTexType v)//定位顶点下标
{
	for (int i = 0; i < G.vexnum; i++)//遍历寻找对应顶点下标
	{
		if (G.vexs[i] == v)
		{
			return i;
		}
	}
	cout << "顶点输入错误,请重新检查!" << endl;//顶点输入错误处理
	return -1;
}
void CreateUDN(AMGraph&G)
{
	cout << "请依次输入总顶点数和总边数:";
	cin >> G.vexnum >> G.arcnum;
	cout << "请输入各顶点信息:" << endl;
	for (int i = 0; i < G.vexnum; i++)//请输入各顶点信息
	{
		cin >> G.vexs[i];
	}
	for (int i = 0; i < G.vexnum; i++)//将邻接矩阵初始化为0
	{
		for (int j = 0; j < G.vexnum; j++)
		{
			if (i == j)
				G.arcs[i][j] = 0;//环的初始化为0
			else
				G.arcs[i][j] = INFINITY;//其余的均初始化为无穷
		}
	}
	for (int k = 0; k < G.arcnum; k++)
	{
		VerTexType v1, v2;
		int w;
		cout << "请依次输第入" << k + 1 << "条边的两个顶点及权值:";
		cin >> v1 >> v2 >> w;
		int i = Locatevex(G, v1);//找到顶点在图中边的下标
		int j = Locatevex(G, v2);
		if (i != -1 && j != -1)//如果能找到对应顶点,对边赋权值
		{
			G.arcs[i][j] = w;
			G.arcs[j][i] = w;
		}
	}
}
int Min(Closedge c[MVNum], AMGraph G)//从各组边中找到最小边
{
	int cost = INFINITY;
	int res;
	for (int i = 0; i < G.vexnum; i++)
	{
		if (c[i].lowcost != 0 && c[i].lowcost < cost)//选出不为环的最小值
		{
			res = i;
			cost = c[i].lowcost;
		}
	}
	return res;//返回下标
}
void MiniSpanTree_Prim(AMGraph G, VerTexType v)
{
	int k = Locatevex(G, v);
	Closedge closedge[MVNum];
	for (int i = 0; i < G.vexnum; i++)//对生成顶点进行初始化
	{
		if (k != i)
		{
			closedge[i].adjvex = G.vexs[k];//顶点初始化为起始点
			closedge[i].lowcost = G.arcs[k][i];//权值初始化为边权值
			
		}
		else
		{
			
			closedge[i].lowcost = 0;
		}
	}
	for (int i = 0; i < G.vexnum-1; i++)
	{
		k = Min(closedge, G);
		VerTexType u0 = closedge[k].adjvex;//旧顶点
		VerTexType v0 = G.vexs[k];//新顶点
		cout << "<" << u0 << "," << v0 << ">";//输出新旧点表示边连接
		closedge[k].lowcost = 0;
		for (int i = 0; i < G.vexnum; i++)
		{
			if (G.arcs[k][i] < closedge[i].lowcost)//对比新并入点的边与旧边哪个小,若新边小,则替换
			{
				closedge[i].lowcost = G.arcs[k][i];
				closedge[i].adjvex = G.vexs[k];
			}
		}
	}
}
/*********克鲁斯卡尔算法***********/

struct Edge{
	int head;//起点
	int tail;//终点
	ArcType lowcost;//权值
};
struct Amgraph {
	VerTexType vexs[MVNum];//顶点信息
	Edge edge[MVNum];//边信息结构数组
	int arcnum;//边数量
	int vexnum;//顶点数量
};
void CreateAMG(Amgraph &G)
{
	cout << "请依次输入总顶点数和总边数:";
	cin >> G.vexnum >> G.arcnum;
	cout << "请输入各顶点信息:" << endl;
	for (int i = 0; i < G.vexnum; i++)//请输入各顶点信息
	{
		cin >> G.vexs[i];
	}
	cout << "请按权值从小到大输入边对应的起点和终点的下标,以及权值:\n";
	for (int k = 0; k < G.arcnum; k++)
	{
		cout << "第" << k+1 << "条边:";
		Edge e;
		cin >> e.head >> e.tail >> e.lowcost;
		G.edge[k] = e;
	}

}

int Find(int *parent, int f)//返回该f点已连接顶点
{
	while (parent[f] > 0)
	{
		f = parent[f];
	}
	return f;
}

void MiniSpanTree_Kruskal(Amgraph G)
{
	int parent[MVNum];//存放最小生成树的顶点
	for (int i = 0; i < G.vexnum; i++)
	{
		parent[i] = 0;
	}
	int m, n;
	for (int i = 0; i < G.arcnum; i++)
	{
		n = Find(parent, G.edge[i].head);
		m = Find(parent, G.edge[i].tail);
		if (n != m)//m=n说明有环
		{
			parent[n] = m;
			cout <<"<"<< G.edge[i].head << "," << G.edge[i].tail <<">";//打印边和权值
		}
	}
}
int main()
{
	cout << "/*********邻接矩阵***********/" << endl;
	AMGraph G;
	CreateUDN(G);
	for (int i = 0; i < G.vexnum; i++)
		cout << '\t' << "v" << i;
	cout << endl;
	for (int i = 0; i < G.vexnum; i++)//输出邻接矩阵
	{
		cout << "v" << i << '\t';
		for (int j = 0; j < G.vexnum; j++)
		{
			cout << G.arcs[i][j] << '\t';
		}
		cout << endl;
	}
	VerTexType v;
	cout << "请输入生成最小二叉树顶点:";
	cin >> v;
	cout << "最小生成树如下所示:";
	MiniSpanTree_Prim(G, v);
	cout << endl;
	Amgraph g;
	CreateAMG(g);
	MiniSpanTree_Kruskal(g);
}

在这里插入图片描述
在这里插入图片描述

发布了330 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43981315/article/details/103915603
今日推荐