最小生成树Prim&Kruskal算法

算法及结构
Prim算法分析

从连通网N=(VE)中的某一顶点U0出发,选择与它关联的具有最小权值的边(U0,v),将 其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u,v),把它的顶点加入到集合U中。如此继续下去, 直到网中的所有顶点都加入到生成树顶点集合U中为止。
假设网中有n个顶点,则第一个进行初始化的循环语句的频度为n,第二个循环语句的频度为n-1;其中有两个内循环:其一是在closedge[v].lowcost中求最小值,其频度为n-1;其二是重新选择具有最小代价的边,其频度为n。由此普里姆算法的空间复杂度为O(n),时间复杂度为O(n^2),与网中的边数无关,因此适用于求边稠密的网的最小生成树。

Kruskal算法分析

从另一途径求网的最小生成树。假设连通网N=(V{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V0),图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。以此类推,直至T中所有顶点都在同一连通分量上为上。
该算法至多对e条边各扫描一次,则每次选择最小代价的边仅需O(loge)的时间(第一次需O(e))。又生成树T的每个连通分量可以看成是一个等价类,则构造T加入新的边的过程类似于求等价类的过程,构造T的过程仅需O(eloge)的时间,由此,克鲁斯卡尔算法的时间复杂度为O(eloge)。

算法比较

算法比较

代码实现
#include<stdio.h>
#include<iostream>
using namespace std;
#define Maxint 999     // 权值
#define Mvnum 100 //最大点数
typedef char Vertextype;   //顶点
typedef  int Arctype;  //边权
typedef struct
{
	Vertextype vexs[Mvnum];         //顶点表
	Arctype arcs[Mvnum][Mvnum];     //邻接矩阵
	int vexum, arcnum;              //当前点数和边数
}AMGraph;
struct a
{
	char adjvex;   //最小边在U中的那个顶点
	int lowcost;    //最小边上的权值
};
struct a closedge[Mvnum];
struct
{
	char Head;
	char Tail;
	int lowcost;
}Edge[Mvnum];
//转换
int locat(AMGraph G, char v)
{ 
	int i=0;
	for ( i= 0; i <G.vexum; i++)
	{
		if (G.vexs[i] == v)
			return i;
	}
	
}
void Createudn(AMGraph& G)
{
	char v1, v2;
	int i, j,w;
	cout<<"请输入邻接矩阵的点数和边数:";
	cin >> G.vexum >> G.arcnum;
	cout<<"输入点  :";
	for (i = 0; i <G.vexum; ++i)
	{
		cin >> G.vexs[i];
	}
	for ( i = 0; i <G.arcnum; i++)
	{
		for ( j = 0; j <G.arcnum; j++)
		{
			G.arcs[i][j] = Maxint;
		}
	}
	cout<<"输入边与权值"<<endl;
	for (int k = 0; k <G.arcnum; k++)
	{
		cin >> v1 >> v2 >>w;
		i = locat(G, v1);
		j = locat(G, v2);
		G.arcs[i][j] = w;
		G.arcs[j][i] = w;
		Edge[k].Head=v1;
		Edge[k].Tail=v2;
		Edge[k].lowcost=w;
	}
}
int Min(AMGraph G,a closedge[])  //返回最小代价边
{
    int min = 999;
    int index = -1;
    for (int i = 0; i <G.vexum;i++)
    {
        if (closedge[i].lowcost < min && closedge[i].lowcost !=0)
        {
            min = closedge[i].lowcost;
            index = i;
        }
    }
    return index;
}

void PRIM(AMGraph G) 
{
	char u='B';
	char u0,v0;
	int sum=0;
	int k,i,j;
//	cout<<"input u  :";
//	cin>>u;
	k=locat(G,u);
	for(j=0;j<G.vexum;++j)
		if(j!=k)
		{
			//			cout<<u<<endl;
			closedge[j].adjvex=u;
			//			cout<<"closedge[j].adjvex  "<<closedge[j].adjvex<<endl;
			closedge[j].lowcost=G.arcs[k][j];
			//			cout<<"closedge[j].lowcost "<<closedge[j].lowcost<<endl;
		}
		closedge[k].lowcost=0;
		for(i=1;i<G.vexum;++i)
		{
			k=Min(G,closedge);
			//			cout<<"K="<<k<<endl;
			u0=closedge[k].adjvex;
			//			cout<<"u0="<<u0<<endl;
			v0=G.vexs[k];
			//			cout<<"v0="<<v0<<endl;
			cout<<u0<<"—"<<v0<<" 边权为 "<<closedge[k].lowcost<<endl;
			sum+=closedge[k].lowcost;
			//			cout<<endl;
			closedge[k].lowcost=0;
			for(j=0;j<G.vexum;++j)
			{
				if(G.arcs[k][j]<closedge[j].lowcost)
				{
					closedge[j].adjvex=G.vexs[k];
//					cout<<"closedge[j].adjvex "<<closedge[j].adjvex<<endl;
					closedge[j].lowcost=G.arcs[k][j];
//					cout<<"closedge[j].lowcost "<<closedge[j].lowcost<<endl;
				}
			}
		}
		cout<<"边权总值为 :"<<sum<<endl;
}     
void show(AMGraph &G)
{
	for(int i=0;i<G.vexum;i++)
	{
		cout<<"*                        ";
		for(int j=0;j<G.vexum;j++)
		{
			if(G.arcs[i][j]==999)
				printf("∞ ");
		//		cout<<"∞"<<" ";
			else
				printf("%02d ",G.arcs[i][j]);
		//	cout<<G.arcs[i][j]<<"  ";
		}
		cout<<"                         *"<<endl;
	}
}
void kruskal(AMGraph &G)
{
	int Vexset[Mvnum];
	int i,j;
	int sum=0;
	char v1,v2;
	int vs1,vs2;
	for(i=0;i<G.vexum;i++) Vexset[i]=i;
	for(i=0;i<G.arcnum-1;i++)
	{
		for(j=i+1;j<G.arcnum;j++)
		{
			if(Edge[j].lowcost<Edge[i].lowcost)
			{
				Edge[G.arcnum].Head=Edge[j].Head;
				Edge[G.arcnum].Tail=Edge[j].Tail;
				Edge[G.arcnum].lowcost=Edge[j].lowcost;
				Edge[j].Head=Edge[i].Head;
				Edge[j].Tail=Edge[i].Tail;
				Edge[j].lowcost=Edge[i].lowcost;
				Edge[i].Head=Edge[G.arcnum].Head;
				Edge[i].Tail=Edge[G.arcnum].Tail;
				Edge[i].lowcost=Edge[G.arcnum].lowcost;
			}
		}
	}
	for(i=0;i<G.arcnum;i++)
	{
		v1=locat(G,Edge[i].Head);
		v2=locat(G,Edge[i].Tail);
		vs1=Vexset[v1];
		vs2=Vexset[v2];
		if(vs1!=vs2)
		{
			cout<<Edge[i].Head<<"—"<<Edge[i].Tail<<"  边权为 "<<Edge[i].lowcost<<endl;
		//	printf("%c %c   %d\n",Edge[i].Head,Edge[i].Tail,Edge[i].lowcost);
			sum+=Edge[i].lowcost;
			for(j=0;j<G.vexum;j++) if(Vexset[j]==vs2) Vexset[j]=vs1;
		}
	}
	cout<<"边权总值为 :"<<sum<<endl;
}
main()
{
	int x;
	AMGraph G;
	Createudn(G);
	printf("*********************************************************************\n");
	printf("*                        最小生成树模拟程序                         *\n");
	printf("*                                                                   *\n");
	show(G);//printf("* show(G);                                                          *\n");
	printf("*                                                                   *\n");
	printf("*                                                                   *\n");
	printf("*            1、普里姆(Prim)算法构造最小生成树                    *\n");
	printf("*            2、克鲁斯卡尔(Kruscal)算法构造最小生成树             *\n");
	printf("*                                                                   *\n");
	printf("*********************************************************************\n");
	
	while(1)
	{
		printf("请选择:");
		scanf("%d",&x);
		switch(x)
		{
		case 1:
			PRIM(G);
			break;
		case 2:
			kruskal(G);	
			break;
		}
	}
}

测试用例

6 10
A B C D E F
A B 6
A C 1
A D 5
B C 5
B E 3
C D 5
C E 6
C F 4
D F 2
E F 6

实现效果图

在这里插入图片描述
最后的最后 xdjmm 点个赞叭
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二琳爱吃肉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值