数据结构(C语言)---克鲁斯卡尔(Kruskal)算法

  • 一、总体思路
  • 二、代码实现步骤
    • 0.结构
    • 1.构建边集数组
    • 2.权值排序
    • 3.生成最小生成树
  • 三、完整代码
  • 四、图解

一、总体思路

总体思路:以边构建
直接找最小权值的边来构建生成树,注意考虑环路的形成

二、代码实现步骤

0.结构

主要两部分
①图:由邻接矩阵构成,包括图的顶点数、边数;
②边集表:包括起点、终点、边数的权值。

#define INFINITY 65535
#define MAXVEX 20
#define MAXEDGE 20typedef struct
{int arc[MAXVEX][MAXVEX];//邻接矩阵int numVertexes, numEdges;//顶点数、边数
}MGraph;//图
typedef struct
{int begin;int end;int weight;
}Edge;//边集数组结构

1.构建边集数组

①用邻接矩阵创建图

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;elseG->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++;}}}

2.权值排序

//交换头尾、权值
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);}
}

3.生成最小生成树

//非常关键
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 <stdio.h>
#include <stdlib.h>
#define INF 65535
#define MAXVEX 20
#define MAXEDGE 20typedef 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;elseG->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;
}

四、图解

关键代码(跟着代码走一遍)

数据结构---克鲁斯卡尔(Kruskal)算法相关推荐

  1. 数据结构与算法(7-3)最小生成树(普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法)

    目录 一.最小生成树简介 二.普里姆算法(Prim) 1.原理 2.存储 2-1.图顶点和权: 2-3. 最小生成树: 3.Prim()函数 3-1.新顶点入树 3-2.保留最小权 3-3. 找到最小 ...

  2. 【数据结构与算法】克鲁斯卡尔(Kruskal)算法

    一,应用场景 公交站问题 1)某城市新增7个站点(A,B,C,D,E,F,G),现在需要修路把7个站点连通 2)各个站点的距离用边线表示(权),比如 A - B距离12公里 3)问:如何修路保证各个站 ...

  3. 【算法】克鲁斯卡尔 (Kruskal) 算法

    目录 1.概述 2.代码实现 2.1.并查集 2.2.邻接矩阵存储图 2.3.邻接表存储图 2.4.测试代码 3.应用 本文参考: <数据结构教程>第 5 版 李春葆 主编 1.概述 (1 ...

  4. 普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法

    图是一种基础又重要的数据结构,图的生成树是图的一个极小连通子图.最小生成树是无向连通网的所有生成树中边的权值之和最小的一棵生成树.求图的最小生成树可以牵引出很多经典的题目,例如在N个城市之间建立通讯网 ...

  5. 对下图所示的连通网络G,用克鲁斯卡尔(Kruskal)算法求G的最小生成树T,请写出在算法执行过程中,依次加入T的边集TE中的边。说明该算法的基本思想及贪心策略,并简要分析算法的时间复杂度

    对下图所示的连通网络G,用克鲁斯卡尔(Kruskal)算法求G的最小生成树T,请写出在算法执行过程中,依次加入T的边集TE中的 边.说明该算法的基本思想及贪心策略,并简要分析算法的时间复杂度

  6. 算法之克鲁斯卡尔(Kruskal)算法

    克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路 具体做法:首先 ...

  7. 算法:通过克鲁斯卡尔(Kruskal)算法,求出图的最小生成树

    之前我给大家分享过用普利姆(Prim)算法来求出图的最小生成树(点我去看看),今天我再给大家分享一个也是求图的最小生成树的克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔(Kruskal)算法,就相当于先 ...

  8. Java实现之克鲁斯卡尔(Kruskal)算法

    一.问题引入 1.问题引入 1)某城市新增7个站点(A,B,C,D,E,F,G),现在需要修路把7个站点连通 2)各个站点的距离用边线表示(权),比如A-B距离12公里 3)问:如何修路保证各个站点都 ...

  9. 普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法

    普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法 普里姆算法的基本思想: 取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w.添加顶点w的条件为:w 和已在生成树上的顶点v ...

  10. 【数据结构】克鲁斯卡尔(Kruskal)算法 —PK— 普里姆(Prim)算法

    目录 一.克鲁斯卡尔(Kruskal)算法 二.普里姆(Prim)算法 三.两个算法对比 求图的最小生成树的典型算法: 克鲁斯卡尔(Kruskal)算法 普里姆(Prim)算法 注:考虑问题的出发点相 ...

最新文章

  1. 为什么要学Access?
  2. Storm【技术文档】-Worker Executor Task的关系
  3. 3亿Docker容器部署的挑战及应对方案
  4. 去除面部黑色素小妙招_去除暗黄皮肤的小妙招 7招让你白皙动人
  5. 深度揭秘铁路 12306 的架构
  6. html 按键hover,按钮hover效果
  7. linux 内核同步机制之complete
  8. 实对称矩阵的特征值求法_特征值的最大值与最小值
  9. iommu intel-iommu实现
  10. 中国行政区划shp地图数据-2022最新数据预览图
  11. 什么是PERT网络分析?
  12. 【HAVENT原创】Salesforce 给字段加上链接
  13. Ubuntu 各版本号和名称对照
  14. FPGA学习任意波函数信号发生器的设计(基于quartus II13.0)
  15. VScode 用socks5代理连接远程服务器
  16. ps—Photoshop中八种颜色模式
  17. Debian Bullseye 更新源备份
  18. NCT 127‘英雄回归’:最精英的一批练习生走着最难的一条路
  19. 维修记录 - 格兰仕光波炉
  20. python灰色波浪线_去除pycharm的波浪线

热门文章

  1. 大数据企业应用合作解决方案案例
  2. PostgreSql数据表清理
  3. csdn写博客怎么添加目录
  4. linux扫描文本含有密码,Linux基础命令常用
  5. ApiCloud开发经验总结
  6. 你知道吗?业余爱好者能用人工智能干什么?
  7. java面试题基本题型
  8. 豌豆荚 软件 android 550 that path is inaccessible sdcard
  9. 网页制作图片格式有哪些
  10. 笔记本计算机故障排除,笔记本电脑开不了机的原因与解决方法