算法基本思想:
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)。