最小生成树--prim算法的c语言描述

本文介绍了Prim算法在寻找加权连通图的最小生成树中的应用。算法从一个任意起点开始,逐步扩展至包含所有顶点,每次选择权值最小的边并确保新增顶点。最终,通过邻接表实现,得出最小生成树的最短路径为16。
摘要由CSDN通过智能技术生成

普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。

算法的描述:

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

3).重复下列操作,直到Vnew = V:

a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;

4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。

网上实在没有找到好的图片于是自己画了一张,这个是《数据结构与算法分析-c语言描述》的图,画得比较抽象- -

边上的数字就是权值

实现这个图的算法

头文件:有权无向图的邻接表

#ifndef _adja2_h
#define _adja2_h
#define SIZE (7)
//定义节点数
#define EGDE (12) 
//定义边数

struct Node;
typedef struct Node *PNode;
typedef struct Node
{
int x;
int quan;
PNode next;
}*EdgeNode;
typedef struct vertex 
{
EdgeNode ele[SIZE];
}*List;

void Adja(List L)
{
EdgeNode S;
int i,j,k,m,v;
for(k=1;k<=SIZE;k++)
	L->ele[k]=NULL;
for(v=0;v<EDGE;v++)
{
	printf("please input information:");
	scanf("%d%d",&i,&j);
	printf("Input quan:");
	scanf("%d",&m);
	S=malloc(sizeof(struct Node));
	S->x=j;
	S->quan=m;
	S->next=L->ele[i];
	L->ele[i]=S;	
	S=malloc(sizeof(struct Node));
	S->x=i;
	S->quan=m;
	S->next=L->ele[j];
	L->ele[j]=S;	
}
}
#endif
prim.c文件实现算法并验证

#include <stdio.h>
#include <stdlib.h>
#include "adja2.h"
#define NotAVertex (-1)
#define SIZE (7)

typedef struct TableEntry
{
int Known;
int Dist;
int Path;
}*Table;
//初始化T
void InitTable(Table T)
{
int i;
for(i=1;i<=SIZE;i++)
{
	T[i].Known=0;
	T[i].Dist=20;
	T[i].Path=NotAVertex;
}
}
//主要函数,生成最小生成树
void Prim(Table *T)
{
int v;
int j,i,k,a;
int min;
List L;
L=malloc(sizeof(struct vertex));
Adja(L);
(*T)[1].Dist=0;
for(;;){
//令v等于Dist最小的未知顶点
        a=1;
        j=1;
//找出节点位置最小的未知节点
	while((*T)[j].Known==1)
		j++;	
//令min等于节点位置最小的节点Dist
	min=(*T)[j].Dist;
//找出最小的值min
	for(i=j+1;i<=SIZE;i++)
		if(!(*T)[i].Known)		
			if((*T)[i].Dist<min)
				min=(*T)[i].Dist;
//从节点1开始令其Dist和min匹配,如果匹配到则说明k节点就是存储最小Dist的未知节点喽
	for(k=1;k<=SIZE;k++){
		if((*T)[k].Known==0&&(*T)[k].Dist==min){
			v=k;		
			break;
		}
	}
//如果所有节点都已知,那么退出循环
	while((*T)[a].Known==1){
		a++;
	}	
	if(a==SIZE+1)
		break;
	if(v==NotAVertex)
		break;
	(*T)[v].Known=1;
//所有与v相邻的未知节点求dw,dw=min(dw,cwv)
		while(L->ele[v]!=NULL){
			if(!(*T)[(L->ele[v]->x)].Known)
				if((*T)[(L->ele[v]->x)].Dist>L->ele[v]->quan){
					(*T)[(L->ele[v]->x)].Dist=L->ele[v]->quan;	
					(*T)[(L->ele[v]->x)].Path=v;
				}
			L->ele[v]=L->ele[v]->next;
		}	
}
}
int main()
{
Table T;
int i,s=0,j;
List L;
T=malloc(sizeof(struct TableEntry)*(SIZE+1));
InitTable(T);
Prim(&T);
//输出最小生成树
for(i=2;i<=SIZE;i++)
	printf("%d-%d\t",i,T[i].Path);
//输出最小生成树的权的和
for(i=2;i<=SIZE;i++)
	s+=T[i].Dist;
printf("%d\n",	s);
return 0;
}

输出最小生成树的最短路径为16

每个顶点相连的点为2-1,3-4,4-1,5-7,6-7,7-4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值