动画参考视频:最小生成树(Kruskal(克鲁斯卡尔)和Prim(普里姆))算法动画演示_哔哩哔哩_bilibili
克鲁斯卡尔算法(Kruskai)
克鲁斯卡尔算法,从边的角度求网的最小生成树,时间复杂度为O(eloge)
。和普里姆算法恰恰相反,更适合于求边稀疏的网的最小生成树。
思路步骤:
1、将边全部提取出来放入一个列表中,从权重小到大依次排序
2、将最小权重的边放入图中与对应的顶点相连
3、要确保边填入后不能形成环,如果形成环就丢弃这条边
4、知道加入了(n-1)条边最小生成树构造完成。(n是树中顶点的数量)
普里姆算法(Prim)
普里姆算法。该算法从顶点的角度为出发点,时间复杂度为O(n2)
,更适合与解决边的绸密度更高的连通网。
思路步骤:
1、从顶点开始出发,选择权重最小的边连接。
2、连接完新的顶点后继续找最小权重边,与已经连接的全部顶点所连接的边都要对比。
3、连接后判断是否形成环,形成的话则放弃,回退权重第二小的边以此类推。
代码没有完善仅供参考
/* 参考的结构体
typedef struct Edgenode //邻接结点
{
int adjvex; //邻接结点存储的数组下标
int weight; //用于存储权值,对于非网图可以不需要
struct Edgenode *next; //链域,指向下一个邻接点
}Edgenode;
typedef struct Vertexnode //顶点 表节点
{
char data; //顶点域,存储顶点信息
Edgenode *firstedge; //边表头指针
}Vertexnode,AdjList[Maxvew];
typedef struct // 数组、顶点、边 结构体
{
AdjList adjList; //顶点数组
int numVertexes,numEdges;//图中当前顶点数和边数
}GrapAdList;
*/ //以上仅供参考
// Prim算法生成最小数
void MIniSpanTree_prim(MGraph G)
{
int min,i,j,k;
int adjvex[MAXVEX]; //保存相关顶点下标
int lowcost[MAXVEX]; //保存相关顶点间边的权值
lowcost[0] = 0; //V0作为最小生成树的根开始遍历 , 权值为0
adjvex[0] = 0; //V0第一个加入
//初始化操作
for(i=1;i<G.numVertexes;i++)
{
lowcost[i]=G.arc[0][i]; //将邻接矩阵的第0行所有权值先加入数组
adjvex[i]=0; //初始化全部先为V0的下标
}
//真正构造最小生成树的过程
for(i=1;i<G.numVertexes;i++)
{
min=INFINITY; // 初始化最小权值为 65535 等不可能数值
j=1;
k=0;
//遍历全部顶点
while(j<G.numVertexes)
{
//找出lowcost数组已储存的最小权值
if(lowcost[j]!=0 && lowcost[j]<min)
{
min= lowcost[j];
k=j; // 将发行的最小权值的下标存入k ,以待使用
}
j++;
}
//打印当前顶点边中权值最小的边
printf("(%d,%d)",adjvex[k],k);
lowcost[k]=0; //将当前顶点权值全部设置为 0 ,表示此顶点已经完成任务,进行下一个顶点的遍历
//邻接矩阵k行逐个遍历全部顶点
for(j=1;j<G.numVertexes;j++)
{
if(lowcost[j]!=G.numVertexes;j++)
{
lowcost[j]=G.arc[k][j];
adjvex[j]=k;
}
}
}
}
//Kruskal算法最小生成树的过程
int Find(int *parent , int f)
{
while(parent[f]>0)
{
f=parent[f];
}
return f;
}
void MIniSpanTree_Kruskal(MGraph G)
{
int i,n,m;
Edge edges[MAGEDGE]; //定义边集数组
int parent[MAXVEX]; //定义parent数组用来判断边与边是否形成环路
for(i=0;i<G,numVertexes;i++)
{
parent[i]=0;
}
for(i=0;i<G,numEdges;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",edges[i].begin,edges[i].end,edges[i].weight);
}
}
}