图--最小生成树--克鲁斯卡尔算法

算法基本思想:
1、将边按权大小从小到大排列,记录边的起点,终点,权;
2、按权值递增遍历所有边,判断新加入的边是否会形成环路,选择不会形成环路的边加入生成树。
#include <stdio.h>
#define MAXInt 65535	//表示两顶点没有直接相连

typedef struct MGraph
{
	int numVertexes;
	int arc[9][9];
}MGraph;

typedef struct Edge
{
	int begin;
	int end;
	int weight;
}Edge;

void QuickSort(Edge *A,int s,int t)
{
	int i=s+1,j=t;//给i和j赋初值
	Edge x=A[s];//把基准元素的值暂存x中
	while(i<=j)
	{
		while(A[i].weight<=x.weight && i<=j)
			i++;//从前向后顺序比较
		while(A[j].weight>=x.weight && j>=i)
			j--;//从后向前顺序比较
		if(i<j)
		{//当条件成立时交换A[i]和A[j]的值
			Edge temp=A[i];
			A[i]=A[j];
			A[j]=temp;
			i++;
			j--;
		}
	}
	//交换A[s]和A[j]的值,得到前后两个子区间A[s]~A[j-1]和A[j+1]~A[t]
	if(s != j)
	{
		A[s]=A[j];
		A[j]=x;
	}
	//在当前左区间内超过一个元素的情况下递归处理左区间
	if(s<j-1)
		QuickSort(A,s,j-1);
	//在当前右区间内超过一个元素的情况下递归处理右区间
	if(j+1<t)
		QuickSort(A,j+1,t);
}

int Find(int *parent,int f)		//查找边线顶点的尾部下标
{
	while(parent[f] != MAXInt)
		f=parent[f];
	return f;
}

void kruskal(MGraph G)
{
	int i,j,n,m,k=0;
	Edge edges[30];
	int parent[10];
	for(i=0;i<G.numVertexes;++i)	//从G中得到所有边的权值
	{
		for(j=0;j<G.numVertexes;++j)
		{
			if(G.arc[i][j] != 0 && G.arc[i][j]<MAXInt)
			{
				edges[k].begin=i;
				edges[k].end=j;
				edges[k].weight=G.arc[i][j];
				++k;
			}
		}
	}
	QuickSort(edges,0,k-1);		//快速排序将edges数组按权值从小到大排序
	//for(i=0;i<k;i++)
	//	printf("(%d, %d) %d\n",edges[i].begin,edges[i].end,edges[i].weight);
	for(i=0;i<G.numVertexes;++i)	//初始化用于判断环路的数组
		parent[i]=MAXInt;
	for(i=0;i<k;++i)	//遍历所有边
	{
		n=Find(parent,edges[i].begin);
		m=Find(parent,edges[i].end);
		if(n != m)		//如果n不等于m,说明此边没有与现有生成树形成环路
		{
			parent[n]=m;	//将此边的结尾顶点放入下标为起点的parent中,表示些顶点已经在生成树集合中
			printf("(%d, %d) %d\n",edges[i].begin,edges[i].end,edges[i].weight);
		}
	}
}

void main(void)
{
//	int i,j;
	MGraph G=	//顶点数和权值表(行下标对应顶点到列下标对应顶点的边权值)
	{
		/*.numVertexes=*/9,	//结构体初始化搞半天原来是VC不支持C99标准
		/*.arc[9][9]=*/{0,10,MAXInt,MAXInt,MAXInt,11,MAXInt,MAXInt,MAXInt,
			        10,0,18,MAXInt,MAXInt,MAXInt,16,MAXInt,12,
					MAXInt,18,0,22,MAXInt,MAXInt,MAXInt,MAXInt,8,
					MAXInt,MAXInt,22,0,20,MAXInt,MAXInt,16,21,
				    MAXInt,MAXInt,MAXInt,20,0,26,MAXInt,7,MAXInt,
					11,MAXInt,MAXInt,MAXInt,26,0,17,MAXInt,MAXInt,
					MAXInt,16,MAXInt,MAXInt,MAXInt,17,0,19,MAXInt,
					MAXInt,MAXInt,MAXInt,16,7,MAXInt,19,0,MAXInt,
					MAXInt,12,8,21,MAXInt,MAXInt,MAXInt,MAXInt,0,},
	};
	/*printf("Enter the number of Vertexes:");
	scanf("%d",&G.numVertexes);
	for(i=0;i<G.numVertexes;++i)
	{
		for(j=0;j<G.numVertexes;++j)
		{
			scanf("%d",&G.arc[i][j]);
		}
	}*/
	kruskal(G);
}

        此算法的Find函数由边数e决定,时间复杂度是O(loge),而外面有一个for循环e次,即O(eloge),还有算上排序的话是O(eloge)+O(eloge)。所以克鲁斯卡尔算法的时间复杂度为O(eloge)。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值