Prim和Kruskal算法源代码

前言

        这两个算法比较好理解,实现起来也没那么困难,相信看到这篇博客的都是学了数据结构了的,所以我就不重复解释这两个算法的思路了。

        这两个代码其实是我在数据结构实验课写的代码,应该可以借鉴点吧。

Prim算法

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define MaxVertexNum 100//最大顶点数
#define INFINITY 65535
typedef int Vertex;//用顶点下标表示顶点
typedef int WeightType;//定义权值类型
typedef char DataType;
int visited[105];
typedef struct GNode {//图结点的定义
	int Nv;//顶点数
	int Ne;//边数
	WeightType G[MaxVertexNum][MaxVertexNum];//邻接矩阵
	DataType Data[MaxVertexNum];//存顶点的数据
}*MGraph;

typedef struct ENode {//边的定义
	Vertex V1, V2;//有向边
	WeightType Weight;//权重
}*Edge;
MGraph CreateGraph(int Nv, int Ne) {//初始化一个有VertexNum个顶点但没有边的图
	MGraph Graph = (MGraph)malloc(sizeof(struct GNode));//建立图
	Graph->Nv = Nv;
	Graph->Ne = Ne;
	//初始化邻接矩阵
	for (Vertex V = 0; V < Graph->Nv; V++)
		for (Vertex W = 0; W < Graph->Nv; W++)
			Graph->G[V][W] = INFINITY;
	for (int i = 0; i < Nv; i++)Graph->Data[i] = i;//顶点表
	return Graph;
}

void InsertEdge(MGraph Graph, Edge E) {//插入边
	Graph->G[E->V1][E->V2] = E->Weight;
	Graph->G[E->V2][E->V1] = E->Weight;//若是无向图,还要插入边<V2,V1>
	//若是有向图,可以把后一句去掉
}
MGraph BuildGraph() {//建立图
	int Nv, Ne;
	scanf("%d %d", &Nv, &Ne);//读入顶点个数和边数
	MGraph Graph = CreateGraph(Nv, Ne);//初始化有Nv个顶点没有边的图
	Edge E = (Edge)malloc(sizeof(struct ENode));//建立边结点
	for (int i = 0; i < Ne; i++) {
		scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
		InsertEdge(Graph, E);
	}
	return Graph;
}
void Print(MGraph Graph) {//将整个图打印出来
	for (int i = 0; i < Graph->Nv; i++) {
		for (int j = 0; j < Graph->Nv; j++)
			printf("%d ", Graph->G[i][j]);
		printf("\n");
	}
}
Vertex FindMinDist(MGraph Graph, WeightType dist[]) {
	Vertex MinV, V;
	WeightType MinDist = INFINITY;
	for (V = 0; V < Graph->Nv; V++) {
		if (dist[V] != 0 && dist[V] < MinDist) {
			MinDist = dist[V];
			MinV = V;
		}
	}
	if (MinDist < INFINITY)return MinV;
	else return -1;
}
int flag[100][100] = { 0 };//用数组flag来标记图中的边是否已经输出过
int Prim(MGraph Graph) {
	WeightType dist[MaxVertexNum], TotalWeight = 0;
	Vertex parent[MaxVertexNum], v, w;
	int VCount = 0;//记录已经连接好的顶点数
	Edge E = (Edge)malloc(sizeof(struct ENode));
	for (v = 0; v < Graph->Nv; v++) {
		dist[v] = Graph->G[0][v];
		parent[v] = 0;
	}
	dist[0] = 0;
	parent[0] = -1;
	VCount++;
	while (1) {
		v = FindMinDist(Graph, dist);
		if (v == -1) break;
		E->V1 = parent[v];
		E->V2 = v; E->Weight = dist[v];
		if (flag[E->V1][E->V2] == 0) {
			printf("%d %d\n", E->V1, E->V2);
			flag[E->V1][E->V2] = 1;
		}
		TotalWeight += dist[v];//加上选择的边的权重
		dist[v] = 0;
		VCount++;
		for (w = 0; w < Graph->Nv; w++) {
			if (dist[w] != 0 && Graph->G[v][w] < INFINITY) {
				if (Graph->G[v][w] < dist[w]) {
					dist[w] = Graph->G[v][w];
					parent[w] = v;
				}
			}
		}
	}
	if (VCount < Graph->Nv)return -1;
	return TotalWeight;
}
int main() {
	MGraph g = BuildGraph();
	if (Prim(g) != -1)printf("%d\n", Prim(g));
	return 0;
}

运行结果

        输出格式是先将选择的边输出,而后输出最小生成树的最小权值。

Kruskal算法


#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct ENode {
	int V1, V2;//两顶点
	int Weight;//权值
}*Edge;
int n, m;//顶点数与边数
void Swap(Edge E[], int i, int j) {
	Edge t = E[i];
	E[i] = E[j];
	E[j] = t;
}
void Sort(Edge E[]) {
	for (int i = 0; i < m; i++) {
		for (int j = i + 1; j < m; j++)
			if (E[i]->Weight > E[j]->Weight) {
				Swap(E, i, j);//交换
			}
	}
}
void Create(Edge E[]) {
	scanf("%d %d", &n, &m);
	for (int i = 0; i < m; i++)
		E[i] = (Edge)malloc(sizeof(struct ENode));
	for (int i = 0; i < m; i++)
		scanf("%d %d %d", &E[i]->V1, &E[i]->V2, &E[i]->Weight);
}
int Find(int parent[], int i) {
	while (parent[i] > 0)
		i = parent[i];
	return i;
}
void Kruskal(Edge E[]) {
	Sort(E);
	int TotalWeight = 0;
	int visited[105][105] = { 0 }, parent[105] = { 0 };

	for (int i = 0; i < m; i++) {
		int x = Find(parent, E[i]->V1);
		int y = Find(parent, E[i]->V2);
		if (x != y) {
			parent[x] = y;
			printf("%d %d\n", E[i]->V1, E[i]->V2);
			TotalWeight += E[i]->Weight;
		}
	}
	printf("%d\n", TotalWeight);
}
int main() {
	Edge E[105];
	Create(E);
	Kruskal(E);
	return 0;
}

运行结果

        输出格式和Prim的是一样的。

结语

         可以看到,输入一样的数据,输出结果是不一样的,具体我就不说了。

        因为刚刚放寒假回到家,我懒癌犯了。。。有点不想动,不想学习,正在尝试开始动脑。其实其他博主写的博客已经写的很好了,我也不太想重复这些东西,直接上源代码就好啦。

猜你喜欢

转载自blog.csdn.net/xiexieyuchen/article/details/121625753