最小生成树算法——kruskal

风流意气都作罢 提交于 2020-03-08 16:38:35

如图,输出最小生成树的生成过程

在这里插入图片描述

算法思想:

  1. 每个边的权值进行从小到大排序
  2. 然后从小到大添加到最小生成树中,若添加一个边后构成环路,则此边不能添加。直到每个顶点都加入到最小生成树中。
  3. 需要一个结构体来存储 每个边的权值与始末顶点。再进行排序。
struct 
{
	VexType head;
	VexType tail;
	ArcType lowcost;
}Edge[MAXSIZE];  //存入每条边的首尾以及权值

通过无向图写出邻接矩阵,调用函数创建邻接矩阵

在这里插入图片描述

VexType vexs[7] = {'0','1','2','3','4','5','6'};
ArcType arcs[7][7] = {{0,17,MAXNUM,MAXNUM,MAXNUM,10,MAXNUM},
					  {17,0,16,MAXNUM,MAXNUM,MAXNUM,14},
					  {MAXNUM,16,0,12,MAXNUM,MAXNUM,MAXNUM},
					  {MAXNUM,MAXNUM,12,0,19,MAXNUM,18},
					  {MAXNUM,MAXNUM,MAXNUM,19,0,25,24},
					  {10,MAXNUM,MAXNUM,MAXNUM,25,0,MAXNUM},
				      {MAXNUM,14,MAXNUM,18,24,MAXNUM,0}};
CreateMGraph(G,vexs,arcs,7); //建表

克鲁斯卡尔图表法

在这里插入图片描述

代码

#ifndef _MGraph_H_
#define _MGraph_H_

#include <iostream>
using namespace std;

#define OK 1
#define ERROR -1
#define OVERFLOW -2
#define MAXSIZE 100
#define MAXNUM 99999 //无穷大

typedef int Status;
typedef char VexType;
typedef int ArcType;
typedef struct
{
	VexType Vexs[MAXSIZE];  //点表
	ArcType Arcs[MAXSIZE][MAXSIZE];  //边表
	int Vexnum;  //顶点个数
	int Arcnum;  //边数
}MGraph;

Status initMGraph(MGraph &G)
{
	G.Vexnum = G.Arcnum = 0;
	return OK;
}

Status CreateMGraph(MGraph &G,VexType vexs[],ArcType arcs[][7],int n) //n为顶点个数
{
	for (int i = 0; i < n; i++)
		G.Vexs[i] = vexs[i];
	G.Vexnum = n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
		{	
			if (arcs[i][j] != 0 && arcs[i][j] != MAXNUM)
				G.Arcnum++;  //对于无向图 除以二即可
			G.Arcs[i][j] = arcs[i][j];
		}
	return OK;
}

Status LocateVex(MGraph G,VexType e)
{
	for (int i = 0; i < G.Vexnum; i++)
		if (G.Vexs[i] == e)
			return i;
	return -1;
}

struct 
{
	VexType head;
	VexType tail;
	ArcType lowcost;
}Edge[MAXSIZE];  //存入每条边的首尾以及权值

int Vexset[MAXSIZE]; //每个顶点所属的连通分量的编号

void CreateEdge(MGraph G)
{
	int k = 0;  //Edge数组的下标
	for (int i = 0; i < G.Vexnum; i++)
		for (int j = i; j < G.Vexnum; j++)  //无向图只需在上三角遍历即可
			if (G.Arcs[i][j] != 0 && G.Arcs[i][j] != MAXNUM)
			{	
				Edge[k].head = G.Vexs[i];
				Edge[k].tail = G.Vexs[j];
				Edge[k].lowcost = G.Arcs[i][j];
				k++;  //最终k的值为G.Arcnum / 2;
			}
}

void Sort(MGraph G) //直接插入排序
{
	CreateEdge(G);
	int i, j;
	for (int i = 1; i < G.Arcnum / 2; i++)
	{
		if (Edge[i].lowcost < Edge[i - 1].lowcost)
		{
			VexType head = Edge[i].head;
			VexType tail = Edge[i].tail;
			ArcType lowcost = Edge[i].lowcost;
			for (j = i - 1; lowcost < Edge[j].lowcost; j--)
				Edge[j + 1] = Edge[j];
			Edge[j + 1].head = head;
			Edge[j + 1].tail = tail;
			Edge[j + 1].lowcost = lowcost;
		}
	}
}
void Kruskal(MGraph G)  //核心算法
{
	Sort(G); //选出Edge中的一个最小边
	for (int i = 0; i < G.Vexnum; i++) //初始化每个顶点为一个连通分量
		Vexset[i] = i;  
	for (int i = 0; i < G.Arcnum / 2; i++)
	{
		int v1 = LocateVex(G,Edge[i].head);
		int v2 = LocateVex(G,Edge[i].tail);
		int vs1 = Vexset[v1];
		int vs2 = Vexset[v2];
		if (vs1 != vs2)  //说明两者不会构成环路,加入到最小生成树
		{
			cout << Edge[i].head << "," << Edge[i].tail << " "<<endl;  //输出边
			for (int j = 0; j < G.Vexnum; j++)  
				if (Vexset[j] == vs2) Vexset[j] = vs1;  //将连通分量vs2的改为vs1
		}
	}
}

#endif

结果

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!