最小生成树--Prim & Kruskal

 Prim

void Prim(MatGraph g, int v)
{
	int lowcost[MAXV]; //边权
	int MIN;
	int closest[MAXV];  //顶点
	int i, j, k;
	for (i = 0; i < g.n; i++)
	{
		lowcost[i] = g.edges[v][i]; //起始点该行的所有权值
		closest[i] = v; //起始点
	}
	for (i = 1; i < g.n; i++)
	{
		MIN = INF;
		for (j = 0; j < g.n; j++)
			if (lowcost[j] != 0 && lowcost[j] < MIN) //更新MIN值,且记录下标结点
			{
				MIN = lowcost[j];
				k = j;
			}
		cout << "边(" << closest[k] << "," << k << ")权为:" << MIN;
		lowcost[k] = 0; //为0表示已在树U中
		for (j = 0; j < g.n; j++)  //对V-U的顶点进行调整
			if (lowcost[j] != 0 && g.edges[k][j] < lowcost[j])  //有比目前lowcost[j]要小的(该行的所有权值)
			{
				lowcost[j] = g.edges[k][j]; //更新
				closest[j] = k;
			}
	}
}

Kruskal

typedef struct {
	int u; //起始
	int v;  //终点
	int w; //权值
}Edge;
#define MAXSIZE 10005
void InsertSort(Edge E[], int e) {}
void Kruskal(MatGraph g)
{
	int i, j;
	int u1, v1;
	int sn1, sn2;
	int k;
	int vset[MAXV];
	Edge E[MAXSIZE]; //存所有边
	k = 0; //e数组下标从0开始记录
	for (i = 0; i < g.n; i++) //对称矩阵
		for (j = 0; j <= i; j++)
			if (g.edges[i][j] != 0 && g.edges[i][j] != INF)
			{
				E[k].u = i; //存入边信息
				E[k].v = j;
				E[k].w = g.edges[i][j];
				k++;
			}
	InsertSort(E, g.e); //排序
	for (i = 0; i < g.n; i++)
		vset[i] = i;

	k = 1; //k表示当前构造生成树的第几条边,初值为1
	j = 0; //E中边的下标,初值为0
	while (k < g.n)
	{
		u1 = E[j].u; //取一条边
		v1 = E[j].v;
		sn1 = vset[u1]; //等到集合所属编号
		sn2 = vset[v1];
		if (sn1 != sn2)
		{
			cout << "(" << u1 << "," << v1 << "):" << E[j].w << endl;
			k++; //生成边数+1
			for (i = 0; i < g.n; i++) //两个集合同一编号 -- 是sn2的直接全赋为sn1
				if (vset[i] == sn2)
					vset[i] = sn1;
		}
		j++;
	}
}

 并查集与堆优化的Kruakal

void KruskalBySet(MatGraph g)
{
	int i, j;
	int u1, v1;
	int sn1, sn2;
	int k;
	UFSTree t[MAXSIZE];
	Edge E[MAXSIZE]; //存所有边
	k = 1; //e数组下标从1开始记录
	for (i = 0; i < g.n; i++) //对称矩阵
		for (j = 0; j <= i; j++)
			if (g.edges[i][j] != 0 && g.edges[i][j] != INF)
			{
				E[k].u = i; //存入边信息
				E[k].v = j;
				E[k].w = g.edges[i][j];
				k++;
			}
	HeapSort(E, g.e); //排序
	MAKE_SET(t, g.n);

	k = 1; //k表示当前构造生成树的第几条边,初值为1
	j = 1; //E中边的下标,初值为1
	while (k < g.n)
	{
		u1 = E[j].u; //取一条边
		v1 = E[j].v;
		sn1 = FIND_SET(t, u1); //等到集合所属编号
		sn2 = FIND_SET(t, v1);
		if (sn1 != sn2)
		{
			cout << "(" << u1 << "," << v1 << "):" << E[j].w << endl;
			k++; //生成边数+1
			UNION(t, u1, v1);
		}
		j++;
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值