Prim算法实现-求连通图的最小生成树(用孩子兄弟CSTree)表示-邻接表(ALGraph)-C语言实现

[图] Prim算法实现-求连通图的最小生成树(用孩子兄弟CSTree)表示-邻接表(ALGraph)-C语言实现
普里姆算法(邻接表)
思想

从某个顶点开始(不要把它看成一个单独的顶点,把它看成只有一个结点的子生成树)
在第一步的生成树的相邻边中,选一条最小的边,将最小的边和边的另一个结点并入子生成树中(生成树就长大了一点)
继续,直到所有的顶点都被并入了生成树

步骤

1.取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w
2.在添加的顶点 w 和已经在生成树上的顶点v 之间必定存在一条边,
3.并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。
4.之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。

性能

O(n^2),适合稠密图(边多的图)
另一个【克鲁斯卡尔算法】O(eloge):适合稀疏图(边少的图)

举例

1.蓝色的顶点:还未考虑的顶点
2.黄色的顶点:已经考虑完的顶点
3.蓝色的线:未考虑的边
4.紫色的线:考虑范围内的边
5.红色的线:生成树的边(最短的边)
在这里插入图片描述

将a纳入考虑的顶点,变成黄色
第一步:考虑黄色顶点【a】

	1.考虑与a相连的所有边(紫色的边),取出				最短的边:18
	2.将最短边,纳入生成树的边(变红色)
	3.将顶点b纳入已考虑的顶点(变黄色)

第二步:考虑黄色的顶点【a,b】

1.考虑与a,b相连的所有边(紫色的边),取出最短的边8
2.将最短边,纳入生成树的边(变红色)
3.将顶点c纳入已考虑的顶点(变黄色)

第三步:继续考虑黄色的顶点【a,b,c】

1.考虑与a,b,c相连的所有边(紫色的边),取出最短的边20
2.将最短边,纳入生成树的边(变红色)
3.将顶点d纳入已考虑的顶点(变黄色)

最终
在这里插入图片描述

实现

记:

1.黄色的顶点,为顶点集【U】,即已落在生成树上的顶点
2.蓝色的顶点,为顶点集【V-U】,即尚未落在生成树上的顶点

设置一个辅助数组

1.下标:顶点v
2.lowcost:记录【黄色的点们】到【v】的最短边
3.adjvex:记录【黄色的点集】中哪一个顶点,到v最短

在这里插入图片描述

邻接表生成
#define VertexType char //点类型
#define VRType int //边类型
#define maxSize 100
void Visit(VertexType e) {
	printf("%c", e);
}

#define MAX_VERTEX_NUM 20
typedef enum { DG, UDG } GraphKind;
typedef struct ArcNode {
	int adjV; //边指向的顶点
	VRType weight; //权重
	struct ArcNode* next;
}ArcNode; //边
typedef struct VNode {
	VertexType data;
	ArcNode* firstarc;
}VNode, AdjList[MAX_VERTEX_NUM]; //顶点
typedef struct {
	GraphKind kind;
	int vernum, arcnum;
	AdjList vers;
}ALGraph;

Status InitGraph_AL(ALGraph* pG) { //初始化
	int i;
	pG->arcnum = 0;
	pG->vernum = 0;
	for (i = 0; i < MAX_VERTEX_NUM; ++i)
		pG->vers[i].firstarc = NULL; //VC++6.0中指针初始化为0xcccccccc
	return OK;
}
int LocateVex_AL(ALGraph G, VertexType e) { //定位值为e的元素下标
	int i;
	for (i = 0; i < G.vernum; ++i) {
		if (G.vers[i].data == e) {
			return i;
		}
	}
	return -1;
}
// 创建无向图的邻接表--带权
Status CreateUDG_AL(ALGraph* pG) {
	//输入规则:顶点数目->弧的数目->各顶点的信息->各条弧的信息
	int i, a, b, w;
	char h = {'\0'}, t = { '\0' };
	ArcNode* p, * q;

	InitGraph_AL(pG); //VC++6.0中指针初始化为0xcccccccc,如果不将指针初始化为NULL,会出错
	//图的类型
	pG->kind = DG;
	//顶点数目
	printf("顶点数目:");
	scanf_s("%d", &i); if (i < 0) return ERROR;
	pG->vernum = i;
	//弧的数目
	printf("\n弧的数目:");
	scanf_s("%d", &i); if (i < 0) return ERROR;
	getchar();
	pG->arcnum = i;
	//各顶点信息
	for (i = 0; i < pG->vernum; ++i)
	{
		printf("第%d顶点信息:", i + 1);
		scanf_s("%c",&h, 1);
		getchar();
		pG->vers[i].data = h;
		//弧的信息
	}
		
	for (i = 0; i < pG->arcnum; ++i) {
		printf("输入第%d边的信息(vi,vj)和权值:", i + 1);
		scanf_s("%c %c %d", &h,1,&t,1, &w); //结点
		getchar();
		a = LocateVex_AL(*pG, h); //定位
		b = LocateVex_AL(*pG, t); //定位
		if (a < 0 || b < 0) return ERROR; //定位错误
		// a-->b
		p = (ArcNode*)malloc(sizeof(ArcNode)); if (!p) exit(OVERFLOW);
		p->adjV = b;p->next = NULL;p->weight = w;
		if (pG->vers[a].firstarc) { //已经有边了

			//寻找尾节点  ----尾插
			for (q = pG->vers[a].firstarc; q->next; q = q->next);//找到最后一条
			
			q->next = p;
		}
		else { //第一条边
			pG->vers[a].firstarc = p;
		}
		// b-->a
		p = (ArcNode*)malloc(sizeof(ArcNode)); if (!p) exit(OVERFLOW);
		p->adjV = a;p->next = NULL;p->weight = w;
		if (pG->vers[b].firstarc) { //已经有边了
			for (q = pG->vers[b].firstarc; q->next; q = q->next); //找到最后一条
			q->next = p;
		}
		else { //第一条边
			pG->vers[b].firstarc = p;
		}
	}
	return OK;
}

求最小生成树-Prim
*----------------------------------------------------------------
 |求最小生成树-Prim                                         |
 ----------------------------------------------------------------*/
#define INF 10000
typedef struct CSNode {
	VertexType data;
	struct CSNode* firstchild;
	struct CSNode* sibling;
	VRType childW; //孩子的边权重
	VRType siblingW; //兄弟的边权重
}CSNode, * CSTree;



//--------生成最小生成树——————————
VRType GetMSTByPrim(ALGraph G, int v0, CSTree* pT) {
	int MST[MAX_VERTEX_NUM]; //当前的生成树:MST[v]=1 表示 结点v在当前的生成树上
	
	VRType sum; //生成树的代价

	VRType lowCost[MAX_VERTEX_NUM]; //当前的生成树 到 结点v 的最小边的权重是lowCost[v]
	
	int lowNode[MAX_VERTEX_NUM];	//lowCost对应的顶点信息--> 到v的最小边是v->lowNode[v],权值为lowCost[v]

	VRType min; //当前的最小边
	int minNode; //最小边的另一个顶点

	CSNode* tmp[MAX_VERTEX_NUM];
	CSNode* csp;

	ArcNode* p;
	int i, j, parent;

	//初始化
	for (i = 0; i < G.vernum; i++) {
		MST[i] = 0;
		lowCost[i] = INF;
	}
	//处理v0结点
	MST[v0] = 1; //将v0并入生成树
	tmp[v0] = (CSNode*)malloc(sizeof(CSNode));

	if (!tmp[v0])
	{
		exit(OVERFLOW);
	}
	//为生成树创建v0结点
	tmp[v0]->data = G.vers[v0].data;
	tmp[v0]->firstchild = tmp[v0]->sibling = NULL; //赋值

	for (p = G.vers[v0].firstarc; p; p = p->next) {
		//当前生成树到adjV结点的最小边是:v0到adjV的边
		lowCost[p->adjV] = p->weight; //记下权重
		lowNode[p->adjV] = v0;		//记下结点
	}

	sum = 0;
	for (i = 0; i < G.vernum - 1; i++) { //还有n-1个结点要处理
		//选出最短的边
		min = INF;   //设定开始的最小值
		for (j = 0; j < G.vernum; j++) {
			// 如果结点j还没有被并入生成树
			if (MST[j] == 0 && lowCost[j] < min) {
				min = lowCost[j];
				minNode = j;    //保存该顶点
			}
		}

		//处理minNode
		MST[minNode] = 1; //并入生成树
		sum += lowCost[minNode]; //生成树的权重
		tmp[minNode] = (CSNode*)malloc(sizeof(CSNode)); if (!tmp[minNode]) exit(OVERFLOW); //为生成树创建minNode结点
		tmp[minNode]->data = G.vers[minNode].data; tmp[minNode]->firstchild = tmp[minNode]->sibling = NULL; //赋值
		//连接边
		parent = lowNode[minNode]; //minNode的爸爸是lowNode[minNode],边的权重为lowCost[minNode]
		if (tmp[parent]->firstchild) { //第一个孩子存在

			//找到最后一个孩子   ------尾插
			for (csp = tmp[parent]->firstchild; csp->sibling; csp = csp->sibling); 
			csp->sibling = tmp[minNode];	  //csp的兄弟是tmp[minNode]
			csp->siblingW = lowCost[minNode]; //边权重
		}
		else { //没有第一个孩子
			tmp[parent]->firstchild = tmp[minNode]; //孩子为tmp[minNode]
			tmp[parent]->childW = lowCost[minNode]; //边的权重为lowCost[minNode]
		}

		//更新minNode
		for (j = 0; j < G.vernum; j++) {
			for (p = G.vers[minNode].firstarc; p; p = p->next) {
				if (MST[p->adjV] == 0 && p->weight < lowCost[p->adjV]) {
					lowCost[p->adjV] = p->weight;
					lowNode[p->adjV] = minNode;
				}
			}
		}
	}

	*pT = tmp[0];
	return sum;
}


该方法只只获得最短路径不生成最小生成树

//--------只是打印生成树结构--------------
VRType GetMSTByPrimNP(ALGraph G, int v0) {
	int MST[MAX_VERTEX_NUM]; //当前的生成树:MST[v]=1 表示 结点v在当前的生成树上

	VRType sum; //生成树的代价

	VRType lowCost[MAX_VERTEX_NUM]; //当前的生成树 到 结点v 的最小边的权重是lowCost[v]

	int lowNode[MAX_VERTEX_NUM] = {0};	//lowCost对应的顶点信息--> 到v的最小边是v->lowNode[v],权值为lowCost[v]
	
	ArcNode* p; 

	VRType min; //当前的最小边

	int minNode; //最小边的另一个顶点
	int i, j;

	//初始化
	for (i = 0; i < G.vernum; i++) {
		MST[i] = 0;
		lowCost[i] = INF;
	}
	//处理v0结点
	MST[v0] = 1; //将v0并入生成树
	
	for (p = G.vers[v0].firstarc; p; p = p->next) {
		//当前生成树到adjV结点的最小边是:v0到adjV的边
		lowCost[p->adjV] = p->weight; //记下权重
		lowNode[p->adjV] = v0;		//记下结点
	}

	sum = 0;
	for (i = 0; i < G.vernum - 1; i++) { //还有n-1个结点要处理
		//选出最短的边
		min = INF;   //设定开始的最小值
		for (j = 0; j < G.vernum; j++) {
			// 如果结点j还没有被并入生成树
			if (MST[j] == 0 && lowCost[j] < min) {
				min = lowCost[j];
				minNode = j;    //保存该顶点
			}
		}

		//处理minNode
		MST[minNode] = 1; //并入生成树
		sum += lowCost[minNode]; //生成树的权重


		printf("%c ->%c :%d\n", G.vers[lowNode[minNode]].data, G.vers[minNode].data ,min);

		//更新minNode
		for (j = 0; j < G.vernum; j++) {
			for (p = G.vers[minNode].firstarc; p; p = p->next) {
				if (MST[p->adjV] == 0 && p->weight < lowCost[p->adjV]) {
					lowCost[p->adjV] = p->weight;
					lowNode[p->adjV] = minNode;
				}
			}
		}
	}
	return sum;
}

完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#ifndef BASE
#define BASE
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int Bool;
#endif

#define VertexType char //点类型
#define VRType int //边类型
#define maxSize 100
void Visit(VertexType e) {
	printf("%c", e);
}

#define MAX_VERTEX_NUM 20
typedef enum { DG, UDG } GraphKind;
typedef struct ArcNode {
	int adjV; //边指向的顶点
	VRType weight; //权重
	struct ArcNode* next;
}ArcNode; //边
typedef struct VNode {
	VertexType data;
	ArcNode* firstarc;
}VNode, AdjList[MAX_VERTEX_NUM]; //顶点
typedef struct {
	GraphKind kind;
	int vernum, arcnum;
	AdjList vers;
}ALGraph;

Status InitGraph_AL(ALGraph* pG) { //初始化
	int i;
	pG->arcnum = 0;
	pG->vernum = 0;
	for (i = 0; i < MAX_VERTEX_NUM; ++i)
		pG->vers[i].firstarc = NULL; //VC++6.0中指针初始化为0xcccccccc
	return OK;
}
int LocateVex_AL(ALGraph G, VertexType e) { //定位值为e的元素下标
	int i;
	for (i = 0; i < G.vernum; ++i) {
		if (G.vers[i].data == e) {
			return i;
		}
	}
	return -1;
}
// 创建无向图的邻接表--带权
Status CreateUDG_AL(ALGraph* pG) {
	//输入规则:顶点数目->弧的数目->各顶点的信息->各条弧的信息
	int i, a, b, w;
	char h = {'\0'}, t = { '\0' };
	ArcNode* p, * q;

	InitGraph_AL(pG); //VC++6.0中指针初始化为0xcccccccc,如果不将指针初始化为NULL,会出错
	//图的类型
	pG->kind = DG;
	//顶点数目
	printf("顶点数目:");
	scanf_s("%d", &i); if (i < 0) return ERROR;
	pG->vernum = i;
	//弧的数目
	printf("\n弧的数目:");
	scanf_s("%d", &i); if (i < 0) return ERROR;
	getchar();
	pG->arcnum = i;
	//各顶点信息
	for (i = 0; i < pG->vernum; ++i)
	{
		printf("第%d顶点信息:", i + 1);
		scanf_s("%c",&h, 1);
		getchar();
		pG->vers[i].data = h;
		//弧的信息
	}
		
	for (i = 0; i < pG->arcnum; ++i) {
		printf("输入第%d边的信息(vi,vj)和权值:", i + 1);
		scanf_s("%c %c %d", &h,1,&t,1, &w); //结点
		getchar();
		a = LocateVex_AL(*pG, h); //定位
		b = LocateVex_AL(*pG, t); //定位
		if (a < 0 || b < 0) return ERROR; //定位错误
		// a-->b
		p = (ArcNode*)malloc(sizeof(ArcNode)); if (!p) exit(OVERFLOW);
		p->adjV = b;p->next = NULL;p->weight = w;
		if (pG->vers[a].firstarc) { //已经有边了

			//寻找尾节点  ----尾插
			for (q = pG->vers[a].firstarc; q->next; q = q->next);//找到最后一条
			
			q->next = p;
		}
		else { //第一条边
			pG->vers[a].firstarc = p;
		}
		// b-->a
		p = (ArcNode*)malloc(sizeof(ArcNode)); if (!p) exit(OVERFLOW);
		p->adjV = a;p->next = NULL;p->weight = w;
		if (pG->vers[b].firstarc) { //已经有边了
			for (q = pG->vers[b].firstarc; q->next; q = q->next); //找到最后一条
			q->next = p;
		}
		else { //第一条边
			pG->vers[b].firstarc = p;
		}
	}
	return OK;
}

/*----------------------------------------------------------------
 |求最小生成树-Prim                                         |
 ----------------------------------------------------------------*/
#define INF 10000
typedef struct CSNode {
	VertexType data;
	struct CSNode* firstchild;
	struct CSNode* sibling;
	VRType childW; //孩子的边权重
	VRType siblingW; //兄弟的边权重
}CSNode, * CSTree;



//--------生成最小生成树——————————
VRType GetMSTByPrim(ALGraph G, int v0, CSTree* pT) {
	int MST[MAX_VERTEX_NUM]; //当前的生成树:MST[v]=1 表示 结点v在当前的生成树上
	
	VRType sum; //生成树的代价

	VRType lowCost[MAX_VERTEX_NUM]; //当前的生成树 到 结点v 的最小边的权重是lowCost[v]
	
	int lowNode[MAX_VERTEX_NUM];	//lowCost对应的顶点信息--> 到v的最小边是v->lowNode[v],权值为lowCost[v]

	VRType min; //当前的最小边
	int minNode; //最小边的另一个顶点

	CSNode* tmp[MAX_VERTEX_NUM];
	CSNode* csp;

	ArcNode* p;
	int i, j, parent;

	//初始化
	for (i = 0; i < G.vernum; i++) {
		MST[i] = 0;
		lowCost[i] = INF;
	}
	//处理v0结点
	MST[v0] = 1; //将v0并入生成树
	tmp[v0] = (CSNode*)malloc(sizeof(CSNode));

	if (!tmp[v0])
	{
		exit(OVERFLOW);
	}
	//为生成树创建v0结点
	tmp[v0]->data = G.vers[v0].data;
	tmp[v0]->firstchild = tmp[v0]->sibling = NULL; //赋值

	for (p = G.vers[v0].firstarc; p; p = p->next) {
		//当前生成树到adjV结点的最小边是:v0到adjV的边
		lowCost[p->adjV] = p->weight; //记下权重
		lowNode[p->adjV] = v0;		//记下结点
	}

	sum = 0;
	for (i = 0; i < G.vernum - 1; i++) { //还有n-1个结点要处理
		//选出最短的边
		min = INF;   //设定开始的最小值
		for (j = 0; j < G.vernum; j++) {
			// 如果结点j还没有被并入生成树
			if (MST[j] == 0 && lowCost[j] < min) {
				min = lowCost[j];
				minNode = j;    //保存该顶点
			}
		}

		//处理minNode
		MST[minNode] = 1; //并入生成树
		sum += lowCost[minNode]; //生成树的权重
		tmp[minNode] = (CSNode*)malloc(sizeof(CSNode)); if (!tmp[minNode]) exit(OVERFLOW); //为生成树创建minNode结点
		tmp[minNode]->data = G.vers[minNode].data; tmp[minNode]->firstchild = tmp[minNode]->sibling = NULL; //赋值
		//连接边
		parent = lowNode[minNode]; //minNode的爸爸是lowNode[minNode],边的权重为lowCost[minNode]
		if (tmp[parent]->firstchild) { //第一个孩子存在

			//找到最后一个孩子   ------尾插
			for (csp = tmp[parent]->firstchild; csp->sibling; csp = csp->sibling); 
			csp->sibling = tmp[minNode];	  //csp的兄弟是tmp[minNode]
			csp->siblingW = lowCost[minNode]; //边权重
		}
		else { //没有第一个孩子
			tmp[parent]->firstchild = tmp[minNode]; //孩子为tmp[minNode]
			tmp[parent]->childW = lowCost[minNode]; //边的权重为lowCost[minNode]
		}

		//更新minNode
		for (j = 0; j < G.vernum; j++) {
			for (p = G.vers[minNode].firstarc; p; p = p->next) {
				if (MST[p->adjV] == 0 && p->weight < lowCost[p->adjV]) {
					lowCost[p->adjV] = p->weight;
					lowNode[p->adjV] = minNode;
				}
			}
		}
	}

	*pT = tmp[0];
	return sum;
}



//--------只是打印生成树结构--------------
VRType GetMSTByPrimNP(ALGraph G, int v0) {
	int MST[MAX_VERTEX_NUM]; //当前的生成树:MST[v]=1 表示 结点v在当前的生成树上

	VRType sum; //生成树的代价

	VRType lowCost[MAX_VERTEX_NUM]; //当前的生成树 到 结点v 的最小边的权重是lowCost[v]

	int lowNode[MAX_VERTEX_NUM] = {0};	//lowCost对应的顶点信息--> 到v的最小边是v->lowNode[v],权值为lowCost[v]
	
	ArcNode* p; 

	VRType min; //当前的最小边

	int minNode; //最小边的另一个顶点
	int i, j;

	//初始化
	for (i = 0; i < G.vernum; i++) {
		MST[i] = 0;
		lowCost[i] = INF;
	}
	//处理v0结点
	MST[v0] = 1; //将v0并入生成树
	
	for (p = G.vers[v0].firstarc; p; p = p->next) {
		//当前生成树到adjV结点的最小边是:v0到adjV的边
		lowCost[p->adjV] = p->weight; //记下权重
		lowNode[p->adjV] = v0;		//记下结点
	}

	sum = 0;
	for (i = 0; i < G.vernum - 1; i++) { //还有n-1个结点要处理
		//选出最短的边
		min = INF;   //设定开始的最小值
		for (j = 0; j < G.vernum; j++) {
			// 如果结点j还没有被并入生成树
			if (MST[j] == 0 && lowCost[j] < min) {
				min = lowCost[j];
				minNode = j;    //保存该顶点
			}
		}

		//处理minNode
		MST[minNode] = 1; //并入生成树
		sum += lowCost[minNode]; //生成树的权重


		printf("%c ->%c :%d\n", G.vers[lowNode[minNode]].data, G.vers[minNode].data ,min);

		//更新minNode
		for (j = 0; j < G.vernum; j++) {
			for (p = G.vers[minNode].firstarc; p; p = p->next) {
				if (MST[p->adjV] == 0 && p->weight < lowCost[p->adjV]) {
					lowCost[p->adjV] = p->weight;
					lowNode[p->adjV] = minNode;
				}
			}
		}
	}
	return sum;
}


void TreeVisit(VertexType e) {
	printf("%c", e);
}
void PrintAsTree(CSTree T, int i) {
	int cnt;
	if (T) {
		//输出空格
		for (cnt = 1; cnt < i; cnt++) printf(" ");
		//输出字符
		TreeVisit(T->data);
		printf("\n");

		PrintAsTree(T->firstchild, i + 1);
		PrintAsTree(T->sibling, i);
	}
}


int main() {
	ALGraph G;
	int sum;
	CSTree T;

	G.kind = UDG;
	CreateUDG_AL(&G);

	sum = GetMSTByPrim(G, 0, &T);
	printf("最小生成的权重和为:%d\n", sum);
	PrintAsTree(T, 1);
	sum = GetMSTByPrimNP(G, 0);
	printf("最小生成的权重和为:%d\n", sum);
	

	return 0;
}



在这里插入图片描述

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍一下Prim算法和Kruskal算法,并提供C语言实现代码。 首先,Prim算法是一种贪心算法,它从一个源节点开始,逐步扩大生成树的规模,直到包含中所有节点。在每一步中,Prim算法选择当前生成树外与生成树内节点距离最短的边,将其加入生成树中。这个过程一直重复,直到生成树包含了所有节点。 其次,Kruskal算法也是一种贪心算法,它将所有边按照权值从小到大排序,然后依次将边加入生成树中,如果加入这条边不会形成环,就将其加入生成树中。这个过程一直重复,直到生成树包含了所有节点。 下面是Prim算法和Kruskal算法C语言实现代码: Prim算法实现代码: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define INF 999999 int n; // 节点数 int graph[100][100]; // 的邻接矩阵 int dist[100]; // 到生成树的最短距离 bool visited[100]; // 是否已访问 int parent[100]; // 最小生成树的父节点 int prim() { // 初始化 for (int i = 1; i <= n; i++) { dist[i] = INF; visited[i] = false; } dist[1] = 0; parent[1] = -1; // 重复 n-1 次 for (int i = 1; i < n; i++) { // 找到到生成树距离最小的节点 u int u = -1; for (int j = 1; j <= n; j++) { if (!visited[j] && (u == -1 || dist[j] < dist[u])) { u = j; } } visited[u] = true; // 更新到生成树的距离和父节点 for (int v = 1; v <= n; v++) { if (!visited[v] && graph[u][v] < dist[v]) { dist[v] = graph[u][v]; parent[v] = u; } } } // 计算最小生成树的权值和 int sum = 0; for (int i = 1; i <= n; i++) { if (parent[i] != -1) { sum += graph[i][parent[i]]; } } return sum; } int main() { // 输入的邻接矩阵和节点数 scanf("%d", &n); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { scanf("%d", &graph[i][j]); } } int minWeight = prim(); printf("最小生成树的权值和为 %d\n", minWeight); return 0; } ``` Kruskal算法实现代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX 100 int n; // 节点数 int parent[MAX]; // 并查集数组 int graph[MAX][MAX]; // 的邻接矩阵 // 并查集查找 int find(int x) { if (parent[x] == x) { return x; } return parent[x] = find(parent[x]); } // 并查集合并 void merge(int x, int y) { int px = find(x); int py = find(y); if (px != py) { parent[px] = py; } } // Kruskal算法 int kruskal() { // 初始化并查集 for (int i = 1; i <= n; i++) { parent[i] = i; } // 将所有边按照权值从小到大排序 int edges[MAX*MAX][3]; int count = 0; for (int i = 1; i <= n; i++) { for (int j = i+1; j <= n; j++) { if (graph[i][j] != 0) { edges[count][0] = i; edges[count][1] = j; edges[count][2] = graph[i][j]; count++; } } } for (int i = 0; i < count-1; i++) { for (int j = i+1; j < count; j++) { if (edges[i][2] > edges[j][2]) { int temp[3]; temp[0] = edges[i][0]; temp[1] = edges[i][1]; temp[2] = edges[i][2]; edges[i][0] = edges[j][0]; edges[i][1] = edges[j][1]; edges[i][2] = edges[j][2]; edges[j][0] = temp[0]; edges[j][1] = temp[1]; edges[j][2] = temp[2]; } } } // 依次加入边,直到生成树包含所有节点 int sum = 0; for (int i = 0; i < count; i++) { int u = edges[i][0]; int v = edges[i][1]; if (find(u) != find(v)) { merge(u, v); sum += edges[i][2]; } } return sum; } int main() { // 输入的邻接矩阵和节点数 scanf("%d", &n); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { scanf("%d", &graph[i][j]); } } int minWeight = kruskal(); printf("最小生成树的权值和为 %d\n", minWeight); return 0; } ``` 以上是Prim算法和Kruskal算法C语言实现代码,希望能够帮到您。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值