数据结构 图(四)

最小生成树的两种算法

1.普利姆算法(Prim)
在这里插入图片描述
输入输出样例

6 10
1 2 3 4 5 6
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6
1->3:1
3->6:4
6->4:2
3->2:5
2->5:3
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<stdlib.h>
#define max 20

typedef struct node
{
	int weiget;//权值
	int ver;//顶点数据
}node;


typedef struct Vertex
{
	int vernum, srcnum;
	int arc[max][max];
	node vertex[max];
}Vertex;

void CreateGraph(Vertex* G)
{
	scanf("%d %d", &G->vernum, &G->srcnum);
	for (int i = 1; i <= G->vernum; i++)
	{
		scanf("%d", &G->vertex[i].ver);
	}
	for (int i = 1; i <= G->vernum; i++)
	{
		for (int j = 1; j <= G->vernum; j++)
		{
			if (i == j)
			{
				G->arc[i][j] = 0;
			}
			else
			{
				G->arc[i][j] = 65535;
			}
		}
	}
	for (int i = 1; i <= G->srcnum; i++)
	{
		int v1, v2;
		scanf("%d %d %d", &v1, &v2, &G->vertex[i].weiget);
		G->arc[v1][v2] = G->vertex[i].weiget;
		G->arc[v2][v1] = G->arc[v1][v2];
	}
}

void Prim_min_tree(Vertex G)
{
	int lowcost[max];//存储最小权值
	int jver[max];//保存相关顶点下标
	lowcost[1] = 0;
	jver[1] = 1;
	for (int i = 2; i <= G.vernum; i++)
	{
		lowcost[i] = G.arc[1][i];
		jver[i] = 1;
	}
	for (int i = 2; i <= G.vernum; i++)
	{
		int min = 65535;
		int p = 2, q = 0;
		while (p <= G.vernum)
		{
			if (lowcost[p] != 0 && lowcost[p] < min)
			{
				min = lowcost[p];
				q = p;
			}
			p++;
		}
		printf("%d->%d:%d\n", jver[q], q, G.arc[jver[q]][q]);
		lowcost[q] = 0;
		for (int j = 2; j <= G.vernum; j++)
		{
			if (lowcost[j] != 0 && G.arc[q][j] < lowcost[j])
			{
				lowcost[j] = G.arc[q][j];//将权值较小的边并入lowcost
				jver[j] = q;
			}
		}
	}
}

int main()
{
	Vertex G;
	CreateGraph(&G);
	Prim_min_tree(G);
	return 0;
}

2.克鲁斯卡尔算法(Kruskal)
在这里插入图片描述将各边按照权值从小到大排序:

begin   1 4 2 3 1 2 3 1 3 5
end     3 6 5 6 4 3 4 2 5 6
weight  1 2 3 4 5 5 5 6 6 6

输入输出样例:

6 10
1 2 3 4 5 6
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6
1->3:1
4->6:2
2->5:3
3->6:4
2->3:5
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<stdlib.h>
#define max 20//输入的最大的顶点个数

typedef struct node
{
	int weiget;//权值
	int ver;//顶点数据
}node;

typedef struct Vertex
{
	int vernum, srcnum;
	int arc[max][max];
	node vertex[max];
}Vertex;

typedef struct Edge//边集结构体
{
	int begin;
	int end;
	int weight;
}Edge;

//构造边集结构体数组
Edge edge[max * (max - 1)];//有max个顶点的强连通图最多有max*(max-1)条边

void CreateGraph(Vertex* G)
{
	scanf("%d %d", &G->vernum, &G->srcnum);
	for (int i = 1; i <= G->vernum; i++)
	{
		scanf("%d", &G->vertex[i].ver);
	}
	for (int i = 1; i <= G->vernum; i++)
	{
		for (int j = 1; j <= G->vernum; j++)
		{
			G->arc[i][j] = 0;
		}
	}
	for (int i = 1; i <= G->srcnum; i++)
	{
		int v1, v2;
		scanf("%d %d %d", &v1, &v2, &G->vertex[i].weiget);
		G->arc[v1][v2] = G->vertex[i].weiget;
		G->arc[v2][v1] = G->arc[v1][v2];
	}
}

void Sort_Edges(Vertex G)//将邻接矩阵G转化为边集数组,之后边集数组从小到大排序
{
	int k = 1;
	for (int i = 1; i <= G.vernum; i++)
	{
		for (int j = i; j <= G.vernum; j++)//这时我们只需要二阶矩阵的上三角矩阵就行了
		{
			if (G.arc[i][j] != 0)
			{
				edge[k].begin = i;
				edge[k].end = j;
				edge[k].weight = G.arc[i][j];
				k++;
			}
		}
	}
	Edge temp;
	for (int i = 1; i < k; i++)
	{
		for (int j = 1; j < k - i; j++)//按权值从小到大对结构体数组edge排序
		{
			if (edge[j].weight > edge[j + 1].weight)
			{
				temp = edge[j];
				edge[j] = edge[j + 1];
				edge[j + 1] = temp;
			}
		}
	}
}

//查找与elem顶点连线的顶点下标
int find(int* jver, int elem)
{
	while (jver[elem] > 0)
	{
		elem = jver[elem];
	}
	return elem;
}

void Kruskal_min_tree(Vertex G)
{
	int jver[max] = { 0 };
	Sort_Edges(G);
	for (int i = 1; i <= G.srcnum; i++)
	{
		int n = find(jver, edge[i].begin);
		int m = find(jver, edge[i].end);
		if (n != m)
		{
			jver[n] = m;
			printf("%d->%d:%d\n", edge[i].begin, edge[i].end, edge[i].weight);
		}
	}
}

int main()
{
	Vertex G;
	CreateGraph(&G);
	Kruskal_min_tree(G);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值