作业1 ———Prim和Kruskal算法求最小生成树

1问题

Prim算法和Kruskal算法构造最小生成树的过程和算法实现
2解析

Prim:在一个加权连通图中,选取一个起始点,在所有相邻点中选取一个权值最小的点与起始点构成点集,在不形成环的情况下重复上述操作,使所有点进入该点集,形成Prim最小生成树。
作业1 ———Prim和Kruskal算法求最小生成树_第1张图片
Kruskal:在一个加权连通图中,Graph[v]是该图的加权边集,循环:从该集合中最小的权值边开始遍历,直到每个顶点都在同一连通分量中(if 一条边的两个顶点不在同一连通分量中,就添加该边到E[new]中),E[new]以边集的形式输出Kruskal法最小生成树。
作业1 ———Prim和Kruskal算法求最小生成树_第2张图片

3设计

Int Prime(int start){
Visit[start]=1;
For(i from 1 to vmax){
For(j from 1 to vmax)
Visit[i]=0;
Dist[i][j]=graph[i][j];
( * Dist[i][i]=INF)
}
While[visitnum For(i from1 to Vmax){
For(j from 1 to Vmax){
If(visit[i]==true && visit[j]==false && Graph[i][j] 更新 dist[i][j] 和 pos[i] pos[j];
}
}
Visit[pos[j]]=true;
Visitnum++;
Path+=dist[i][i];
Mp[][]记录distp[i][j];
}
}

bool is-same-set(){}判断两个点是否为同一连通分量
int set(){}查询根节点
void merge_in_same_set(){}将两个点归为同一连通分量
int Kruskal(){
判断结构体数组中 i 和 j是否在同一连通分量,是的话不加入sum,不是的话加入
}

4分析

Prim:
While{
For(){
For(){
}
}
}
时间复杂度O(n^3) 空间复杂度O(1)
Kruskal:
时间复杂度:O(n^2) 空间复杂度O(1)
5源码

#include
#include
#include
#include
#define v 4
int set[v];
int mp[v][v] = { 0 };
int Graph[v][v];
bool visit[v] = {false};
struct road {
	int i;
	int j;
	int w;
}r[4];
void  Prim(int Graph[][v],int start) {	
	int visitnum = 1;
	visit[start] = true;
	while (visitnum < v) {
		int dist = 1000;
		int pos = -1, m = -1;
		for (int i = 0; i < v; i++) {
			for (int j = 0; j < v; j++) {
				if (visit[i] == true && visit[j] == false && Graph[i][j] < dist)
				{		
				dist= Graph[i][j];
				pos = j, m = i;
			     }
			}
		}
		visitnum++;
		visit[pos] = true;
	    mp[m][pos] = dist;
 	}	
		for (int i = 0; i < v; i++) {
			for (int j = 0; j < v; j++) {
				printf("%d ", mp[i][j]);
			}
			printf("\n");
		}
}


int find(int x) //查询集合根节点
{
	return set[x] == x ? set[x] : set[x] = find(set[x]);
}
bool is_same_set(int x, int y) //判断是否为一个集合
{
	return find(x) == find(y);
}
void merge_in_same_set(int x, int y) //合并集合
{
	set[find(x)] = find(y);
}
void Kruskal() {
	int sum = 0;
	for (int i = 0; i < v; i++)//初始化集合,每一个数都是一个集合
		set[i] = i;
	for (int i = 0; i < v;i++) {
		for (int j = 0; j < v;j++) {
			if (r[j].w > r[j].w) {
				int tmp = r[j].w;
				r[j].w = r[j + 1].w;
				r[j + 1].w = tmp;
			}
		}
	}
	for (int i = 0; i < v; i++)
		if (!is_same_set(r[i].i, r[i].j))//判断是否在同一集合
		{
			merge_in_same_set(r[i].i, r[i].j);//合并集合
			sum += r[i].w;
		}
	printf("%d\n", sum);
}

int main() {
	memset(Graph, 0x3f3f3f3f, sizeof(Graph));
	int m;
	scanf_s("%d", &m);//输入图的边数
	while (m--) {
		int i, j, w;
		scanf_s("%d%d%d", &i, &j, &w);//输入连接两条边的点 和权值
		Graph[i][j] = Graph[j][i] = w;
		r[i] = { i,j,w };
	}
	Prim(Graph, 1);
	Kruskal();

}

你可能感兴趣的:(算法)