数据结构10 图的经典算法-- Kruskal算法

系列文章目录

深度优先算法 DFS

广度优先算法 BFS

Prim算法

Kruskal算法

Dijkstra算法

系列文章将会写图的经典的几种,有错误的地方欢迎在评论中提出。


前言

提示:Prim算法和Kruskal算法是为了实现图中的最小生成树的算法。不同的是,Prim算法从节点上开始入手,而Kruskal算法是从边上入手,各有优劣。


提示:以下是本篇文章正文内容,下面案例可供参考

一、 Kruskal算法简介

Kruskal算法的从最小的边开始,将其连接成一个生成树,并在连接时判断是否在一个生成树上,直到遍历了n-1条边。
在这里插入图片描述

该处使用的url网络请求的数据。


二. Kruskal算法的代码实现(c语言)

代码如下(示例):

1. Kruskal算法的部分

void spantree_kruskal(graphmtx *g)
{
	edge *e=(edge *)malloc(sizeof(edge)*g->numedge);
	int n=0;
	for(int i=0;i<g->numvertice;i++)
	{
		for(int j=i+1;j<g->numvertice;j++)
		{
			if(g->edge[i][j]!=max)
			{
				e[n].x=i;
				e[n].y=j;
				e[n++].cost=g->edge[i][j];
			}
		}
	}
		
	for(i=0;i<n-1;i++)
	{
		for(int j=0;j<n-i-1;j++)
		{
			if(e[j].cost>e[j+1].cost)
			{
				swap(e[j],e[j+1]);
			}
		}
	}

/*	for(i=0;i<n;i++)
	{
		printf("%d-->%d:%d",e[i].x,e[i].y,e[i].cost);
		printf("\n");
	}
	*/
	int father[max];
	for(i=0;i<g->numvertice;i++)
	{
		father[i]=i;
	}
	int x,y,cnt=0,k=0;
	while(cnt<g->numvertice-1)
	{
		x=getfather(e[k].x,father);
		y=getfather(e[k].y,father);
		if(x!=y)
		{
			father[x]=y;
			cnt++;
			printf("%c-->%c:%d",g->verticelist[e[k].x],g->verticelist[e[k].y],e[k].cost);
			printf("\n");
		}
		//printf("%c-->%c:%d",g->verticelist[e[k].x],g->verticelist[e[k].y],e[k].cost);
		//printf("%d-->%d:%d",e[k].x,e[k].y,e[k].cost);
		k++;
	}

}

2.全部代码

#include<stdio.h>
#include<malloc.h>
#include<assert.h>

#define defaultnum 10
#define t char
#define max 100

typedef struct graphmtx
{
	int maxvertice;
	int numvertice;
	int numedge;

	t *verticelist;
	int **edge;
}graphmtx;


typedef struct edge
{
	int x;
	int y;
	int cost;
}edge;


void initgraph(graphmtx *g);
void showgraph(graphmtx *g);
void insertvertice(graphmtx *g,t e);
int findpos(graphmtx *g,t e);
void insertedge(graphmtx *g,t e1,t e2,int cost);
void spantree_kruskal(graphmtx *g);
void swap(edge &e1,edge &e2);
int getfather(int x,int *father);



void main()
{
	graphmtx gm;
	initgraph(&gm);
	insertvertice(&gm,'A');
	insertvertice(&gm,'B');
	insertvertice(&gm,'C');
	insertvertice(&gm,'D');
	insertvertice(&gm,'E');
	insertvertice(&gm,'F');
	insertvertice(&gm,'G');
	insertedge(&gm,'A','B',19);
	insertedge(&gm,'A','E',14);
	insertedge(&gm,'A','G',18);
	insertedge(&gm,'C','B',5);
	insertedge(&gm,'E','B',12);
	insertedge(&gm,'D','B',7);
	insertedge(&gm,'E','D',8);
	insertedge(&gm,'C','D',3);
	insertedge(&gm,'D','F',21);
	insertedge(&gm,'G','F',27);
	insertedge(&gm,'E','G',16);
	showgraph(&gm);
	printf("\n");
	spantree_kruskal(&gm);
	}



void initgraph(graphmtx *g)
{
	g->maxvertice=defaultnum;
	g->numedge=g->numvertice=0;

	g->verticelist=(t*)malloc(sizeof(t)*defaultnum);
	assert(g->verticelist !=NULL);

	g->edge=(int **)malloc(sizeof(int *)*defaultnum);
	assert(g->edge!=NULL);

	for(int i=0;i<g->maxvertice;++i)
	{
		g->edge[i]=(int *)malloc(sizeof(int)*defaultnum);
	}
	for(i=0;i<g->maxvertice;++i)
	{
		for(int j=0;j<g->maxvertice;++j)
		{
			if(i==j)
				g->edge[i][j]=0;
			else
				g->edge[i][j]=max;
		}
	}
}



void showgraph(graphmtx *g)
{
	printf("  ");
	for(int i=0;i<g->numvertice;i++)
		printf("%c ",g->verticelist[i]);
	printf("\n");
	for(i=0;i<g->numvertice;i++)
	{
		printf("%c ",g->verticelist[i]);
		for(int j=0;j<g->numvertice;j++)
		{
			if(g->edge[i][j]==max)
				printf("@ ");
			else
			{
				printf("%d ",g->edge[i][j]);
			}
		}
		printf("\n");
	}
	printf("\n");

}


void insertvertice(graphmtx *g,t e)
{
	if(g->numedge>g->numvertice)
	{
		printf("已满");
		return;
	}
	g->verticelist[g->numvertice++]=e;

}


int findpos(graphmtx *g,t e)
{
	for(int i=0;i<g->numvertice;i++)
	{
		if(g->verticelist[i]==e)
			return i;
	}
	return -1;
}



void insertedge(graphmtx *g,t e1,t e2,int cost)
{
	int p=findpos(g,e1);
	int w=findpos(g,e2);
	if(p==-1||w==-1)
		return;
	if(g->edge[p][w]!=max)
		return;
	g->edge[p][w]=g->edge[w][p]=cost;
}


void spantree_kruskal(graphmtx *g)
{
	edge *e=(edge *)malloc(sizeof(edge)*g->numedge);
	int n=0;
	for(int i=0;i<g->numvertice;i++)
	{
		for(int j=i+1;j<g->numvertice;j++)
		{
			if(g->edge[i][j]!=max)
			{
				e[n].x=i;
				e[n].y=j;
				e[n++].cost=g->edge[i][j];
			}
		}
	}
		
	for(i=0;i<n-1;i++)
	{
		for(int j=0;j<n-i-1;j++)
		{
			if(e[j].cost>e[j+1].cost)
			{
				swap(e[j],e[j+1]);
			}
		}
	}

/*	for(i=0;i<n;i++)
	{
		printf("%d-->%d:%d",e[i].x,e[i].y,e[i].cost);
		printf("\n");
	}
	*/
	int father[max];
	for(i=0;i<g->numvertice;i++)
	{
		father[i]=i;
	}
	int x,y,cnt=0,k=0;
	while(cnt<g->numvertice-1)
	{
		x=getfather(e[k].x,father);
		y=getfather(e[k].y,father);
		if(x!=y)
		{
			father[x]=y;
			cnt++;
			printf("%c-->%c:%d",g->verticelist[e[k].x],g->verticelist[e[k].y],e[k].cost);
			printf("\n");
		}
		//printf("%c-->%c:%d",g->verticelist[e[k].x],g->verticelist[e[k].y],e[k].cost);
		//printf("%d-->%d:%d",e[k].x,e[k].y,e[k].cost);
		k++;
	}

}


void swap(edge &e1,edge &e2)
{
	int x=e1.x;
	int y=e1.y;
	int cost=e1.cost;
	e1.x=e2.x;
	e1.y=e2.y;
	e1.cost=e2.cost;
	e2.x=x;
	e2.y=y;
	e2.cost=cost;

}

int getfather(int x,int *father)
{
	if(x!=father[x])
		father[x]=getfather(father[x],father);
	return father[x];
}

代码实现结果如下
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值