Kruskal算法

Kruskal算法的基本思想是:
1 、对于图G=(V,E),开始时,将顶点集分为|V|个等价类,每个等价类包括一个顶点;
2、然后,以权的大小为顺序处理各条边,如果某条边连接两个不同等价类的顶点,则这条边被添加到MST,两个等价类被合并为一个;
3、反复执行此过程,直到只剩下一个等价类。

借用 Hackbuteer1博客中的图片如下:

#include "GraphLink.h"
#include "ParTree.h"
#include "MinHeap.h"

class Dist
{
public:
	int index; //顶点的索引值,仅Dijkstra算法会用到
	int length;//顶点之间的距离
	int pre;//路径最后经过的顶点

	bool operator < (const Dist &dist)
	{
		return length < dist.length;
	}

	bool operator <= (const Dist &dist)
	{
		return length <= dist.length;
	}

	bool operator > (const Dist &dist)
	{
		return length > dist.length;
	}

	bool operator >= (const Dist &dist)
	{
		return length >= dist.length;
	}

	bool operator == (const Dist &dist)
	{
		return length == dist.length;
	}
};

void addEdgeToMST(Edge &edge,Edge* &MST,int n)// 将边e加到MST中
{
	MST[n] = edge;
}

//最小支撑树的Kruskal算法,
//参数G是图,参数MST是保存最小支撑树中所有边的数组
void Kruskal(Graph& G, Edge* &MST)  {

	ParTree<int> A(G.verticesNum());//等价类
	MinHeap<Edge> H(G.edgesNum());//最小值堆(minheap)
	MST = new Edge[G.edgesNum()-1];//最小支撑树
	int MSTTag = 0;//最小支撑树边的标号

	//将图的所有边插入最小值堆H中
	for(int i = 0; i < G.verticesNum();i++)
	{
		for(Edge edge = G.firstEdge(i);G.isEdge(edge); edge = G.nextEdge(edge))
		{
			if(G.fromVertex(edge) < G.toVertex(edge))//因为是无向图,所以应防止重复插入
			{
				H.insert(edge);
			}
		}
	}

	int EquNum=G.verticesNum();              //开始时有|V|个等价类
	while(EquNum > 1)
	{
		bool heapEmpty = H.isEmpty();
		Edge edge;

		if(!heapEmpty)
		{
			
			H.removeMin(edge);//获得下一条权最小的边
		}

		if(heapEmpty || edge.weight == INFINITE)
		{
			cout << "不存在最小支撑树." <<endl;
			delete [] MST;                     //释放空间
			MST=NULL;                   //MST是空数组
			return;
		}

		int from = G.fromVertex(edge);//记录该条边的信息
		int to = G.toVertex(edge);
		if(A.diffrent(from,to))//如果边e的两个顶点不在一个等价类
		{
			A.unionTree(from,to);//将边e的两个顶点所在的两个等价类合并为一个
		}

		addEdgeToMST(edge,MST,MSTTag++);//将边e加到MST
		EquNum--;//将等价类的个数减1
	}
}

int A[N][N] =  {
//   v0  v1  v2  v3  v4  v5  v6     
	0, 20,  0,  0,  1,  0,  0,
	20, 0,  6,  4,  0,  0,  0,
	0,  6,  0,  0,  0,  0,  2,
	0,  4,  0,  0,  0, 12,  8,
	1,  0,  0,  0,  0, 15,  0,
	0,  0,  0, 12, 15,  0, 10,
	0,  0,  2,  8,  0, 10,  0

};

int main()
{
	GraphLink<ListUnit> graphLink(N);     // 建立图 
	graphLink.initGraph(graphLink, A,N); // 初始化图

	Edge *D;
	Kruskal(graphLink,D);
	for (int i = 0; i < N - 1; i ++)
	{
		cout << "V" << D[i].from << "->V" << D[i].to << "   Weight is : " << D[i].weight << endl;

	}
	system("pause");
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值