总体思路:以边构建
直接找最小权值的边来构建生成树,注意考虑环路的形成
主要两部分
①图:由邻接矩阵构成,包括图的顶点数、边数;
②边集表:包括起点、终点、边数的权值。
#define INFINITY 65535
#define MAXVEX 20
#define MAXEDGE 20
typedef struct
{
int arc[MAXVEX][MAXVEX];//邻接矩阵
int numVertexes, numEdges;//顶点数、边数
}MGraph;//图
typedef struct
{
int begin;
int end;
int weight;
}Edge;//边集数组结构
①用邻接矩阵创建图
void CreateMGraph(MGraph* G)
{
int i, j;
G->numEdges = 15;
G->numVertexes = 9;
//初始化邻接矩阵
for (i = 0; i < G->numVertexes; i++)
{
for (j = 0; j < G->numVertexes; j++)
{
if (i == j)
G->arc[i][j] = 0;
else
G->arc[i][j] = G->arc[j][i] = INFINITY;
}
}
G->arc[0][1] = 10;
G->arc[0][5] = 11;
G->arc[1][2] = 18;
G->arc[1][8] = 12;
G->arc[1][6] = 16;
G->arc[2][8] = 8;
G->arc[2][3] = 22;
G->arc[3][8] = 21;
G->arc[3][6] = 24;
G->arc[3][7] = 16;
G->arc[3][4] = 20;
G->arc[4][7] = 7;
G->arc[4][5] = 26;
G->arc[5][6] = 17;
G->arc[6][7] = 19;
for (i = 0; i < G->numVertexes; i++)
{
for (j = i; j < G->numVertexes; j++)
{
G->arc[j][i] = G->arc[i][j];
}
}
}
②构建边集数组
int i, j;
int k = 0;
int parent[MAXVEX];//判断是否形成环的数组
Edge edges[MAXEDGE];//边集数组,edge的结构为begin,end,weight,均为整型
//构建边集数组
//将邻接矩阵转换为边集数组
for (i = 0; i < G.numVertexes - 1; i++)
{
for (j = i + 1; j < G.numVertexes ; j++)
{
if (G.arc[i][j] < INFINITY)
{
edges[k].begin = i;
edges[k].end = j;
edges[k].weight = G.arc[i][j];
k++;
}
}
}
//交换头尾、权值
void Swap(Edge* edges, int i, int j)
{
int t;
t = edges[i].begin;
edges[i].begin = edges[j].begin;
edges[j].begin = t;
t = edges[i].weight;
edges[i].weight = edges[j].weight;
edges[j].weight = t;
t = edges[i].end;
edges[i].end = edges[j].end;
edges[j].end = t;
}
//权值排序
void Sort(Edge edges[], MGraph* G)
{
int i, j;
for (i = 0; i < G->numEdges; i++)
{
for (j = i+1; j < G->numEdges; j++)//选择排序
{
if (edges[i].weight > edges[j].weight)
{
Swap(edges, i, j);
}
}
}
printf("权排序之后的为:\n");
for (i = 0; i < G->numEdges; i++)
{
printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);
}
}
//非常关键
int Find(int* parent, int f)
{
while (parent[f] > 0)//已加入生成树集合
{
f = parent[f];//找到与它连通的最大顶点
}
//若该点没有加入生成树集合,就返回该点本身
return f;
}
void MiniSpanTree_Kruskal(MGraph G)
{
int i, j,n,m;
int k = 0;
int parent[MAXVEX];//判断是否形成环的数组
Edge edges[MAXEDGE];//边集数组,edge的结构为begin,end,weight,均为整型
//构建边集数组的代码
//排序
Sort(edges, &G);
/* ************* 算法关键 ****************** */
for (i = 0; i < G.numVertexes; i++)
parent[i] = 0;//初始化数组
printf("打印最小生成树:\n");
for (i = 0; i < G.numEdges; i++)/* 循环每一条边 */
{
n = Find(parent, edges[i].begin);//从起点开始找
m = Find(parent, edges[i].end);//从终点开始找
if (n != m)//没有形成环
{
parent[n] = m;//将此边的结尾顶点 放入 下标为起点的parent中,
//表示该顶点已在生成树集合中
printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);
}
}
}
#include
#include
#define INF 65535
#define MAXVEX 20
#define MAXEDGE 20
typedef struct
{
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}MGraph;
typedef struct
{
int begin;
int end;
int weight;
}Edge;//边集数组结构
void CreateMGraph(MGraph* G)
{
int i, j;
G->numEdges = 15;
G->numVertexes = 9;
//初始化邻接矩阵
for (i = 0; i < G->numVertexes; i++)
{
for (j = 0; j < G->numVertexes; j++)
{
if (i == j)
G->arc[i][j] = 0;
else
G->arc[i][j] = G->arc[j][i] = INF;
}
}
G->arc[0][1] = 10;
G->arc[0][5] = 11;
G->arc[1][2] = 18;
G->arc[1][8] = 12;
G->arc[1][6] = 16;
G->arc[2][8] = 8;
G->arc[2][3] = 22;
G->arc[3][8] = 21;
G->arc[3][6] = 24;
G->arc[3][7] = 16;
G->arc[3][4] = 20;
G->arc[4][7] = 7;
G->arc[4][5] = 26;
G->arc[5][6] = 17;
G->arc[6][7] = 19;
for (i = 0; i < G->numVertexes; i++)
{
for (j = i; j < G->numVertexes; j++)
{
G->arc[j][i] = G->arc[i][j];
}
}
}
//交换头尾、权值
void Swap(Edge* edges, int i, int j)
{
int t;
t = edges[i].begin;
edges[i].begin = edges[j].begin;
edges[j].begin = t;
t = edges[i].weight;
edges[i].weight = edges[j].weight;
edges[j].weight = t;
t = edges[i].end;
edges[i].end = edges[j].end;
edges[j].end = t;
}
//权值排序
void Sort(Edge edges[], MGraph* G)
{
int i, j;
for (i = 0; i < G->numEdges; i++)
{
for (j = i+1; j < G->numEdges; j++)//选择排序
{
if (edges[i].weight > edges[j].weight)
{
Swap(edges, i, j);
}
}
}
printf("权排序之后的为:\n");
for (i = 0; i < G->numEdges; i++)
{
printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);
}
}
//非常关键
int Find(int* parent, int f)
{
while (parent[f] > 0)//已加入边集数组
{
f = parent[f];//找到与它连通的最大顶点
}
return f;
}
void MiniSpanTree_Kruskal(MGraph G)
{
int i, j,n,m;
int k = 0;
int parent[MAXVEX];//判断是否形成环的数组
Edge edges[MAXEDGE];//边集数组,edge的结构为begin,end,weight,均为整型
//构建边集数组
//将邻接矩阵转换为边集数组
for (i = 0; i < G.numVertexes - 1; i++)
{
for (j = i + 1; j < G.numVertexes ; j++)
{
if (G.arc[i][j] < INF)
{
edges[k].begin = i;
edges[k].end = j;
edges[k].weight = G.arc[i][j];
k++;
}
}
}
//排序
Sort(edges, &G);
/* ************* 算法关键 ****************** */
for (i = 0; i < G.numVertexes; i++)
parent[i] = 0;//初始化数组
printf("打印最小生成树:\n");
for (i = 0; i < G.numEdges; i++)/* 循环每一条边 */
{
n = Find(parent, edges[i].begin);//从起点开始找
m = Find(parent, edges[i].end);//从终点开始找
if (n != m)//没有形成环
{
parent[n] = m;//将此边的结尾顶点 放入 下标为起点的parent中,
//表示该顶点已在生成树集合中
printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);
}
}
}
int main()
{
MGraph G;
CreateMGraph(&G);
MiniSpanTree_Kruskal(G);
return 0;
}