数据结构——Kruskal算法

基本思想:(加边)
1.设无向连通网为G=(V, E),令G的最小生成树为T=(U, TE),其初态为U=V,TE={ },
2.然后,按照边的权值由小到大的顺序,考察G的边集E中的各条边。
 2.1若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;
 2.2若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,
 2.3如此下去,当T中的连通分量个数为1时,此连通分量便为G的一棵最小生成树。
伪代码:

算法:Kruskal算法
输入:无向连通图G={V,E}
输出:最小生成树T={U,TE}
   1. 初始化:U=V;  TE={}2. 循环直到T中的连通分量个数为1  
       2.1 在E中寻找最短边(u,v);
       2.2 如果顶点u、v位于T的两个不同连通分量,则
           2.2.1 将边(u,v)并入TE;
           2.2.2 将这两个连通分量合并为一个;
     2.3 在E中标记边(u,v),使得(u,v)不参加后续最短边的选取;

代码实现:

struct EdgeType //定义边集数组的元素类型
{
int from, to, weight; //假设权值为整数
};

const int MaxVertex = 10; //图中最多顶点数
const int MaxEdge = 100; //图中最多边数
template //定义模板类
class EdgeGraph 
{
public:
	EdgeGraph(DataType a[], int n, int e);//构造函数,生成n个顶点e条边的连通图
	~EdgeGraph(); //析构函数
	void Kruskal(); //Kruskal算法求最小生成树
private:
	int FindRoot(int parent[], int v);//求顶点v所在集合的根
	DataType vertex[MaxVertex];//存储顶点的一维数组
	EdgeType edge[MaxEdge];//存储边的边集数组
	int vertexNum, edgeNum; 
};

template<T>
EdgeGraph::EdgeGraph(DataType a[], int n, int e)
{
	int i, j, k, w;
	vertexNum = n; edgeNum = e;
	for (i = 0; i < vertexNum; i++)
	vertex[i] = a[i];
	for (k = 0; k < edgeNum; k++)
	{
		cout << "请输入边依附的两个顶点的编号,以及边上的权值:";
		cin >> i >> j >> w; //输入边依附的两个顶点的编号
		edge[k].from = i; edge[k].to = j; edge[k].weight = w;
	}
}

template<T>
EdgeGraph::~EdgeGraph(){}

template<T>
void EdgeGraph :: Kruskal()
{
	int num = 0, i, vex1, vex2;
	int parent[vertexNum]; //双亲表示法存储并查集
	for (i = 0; i < vertexNum; i++)
		parent[i] = -1; //初始化n个连通分量
	for (num = 0, i = 0; num < vertexNum - 1; i++) //依次考察最短边
	{
		vex1 = FindRoot(parent, edge[i].from);
		vex2 = FindRoot(parent, edge[i].to);
		if (vex1 != vex2){ //位于不同的集合
			cout << "(" << edge[i].from << "," << edge[i].to << ")" << edge[i].weight << endl;
			parent[vex2] = vex1; //合并集合
			num++;
		}
	}
}

template<T>
int EdgeGraph :: FindRoot(int parent[ ], int v) //求顶点v所在集合的根
{
	int t = v;
	while (parent[t] > -1) //求顶点t的双亲一直到根
		t = parent[t]; 
	return t;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值