克鲁斯卡尔算法

C数据结构与算法-基础整理-图-06:克鲁斯卡尔算法详解

对着背影说爱祢 提交于 2020-02-19 04:08:47
详解最小生成树中的克鲁斯卡尔算法 0x01.关于克鲁斯卡尔算法 Kruskal算法 是一种用来查找 最小生成树 的算法,由Joseph Kruskal在1956年发表。克鲁斯卡尔算法主要针对边集数组展开。 0x02.基础代码 这个算法主要是针对边集数组,先来看一下边集数组的结构: //边集数组 typedef struct { int begin; int end; int weight; }Edge; 通常用到邻接矩阵,所以还需要由邻接矩阵转化为边集数组。另外这个算法还需要按照边的权值升序排序。 void OperationEdge(Graph G, Edge* edges) { int i, j,k; k = 0; for (i = 0; i < G.numv; i++) { for (j = i+1; j < G.numv; j++)//只需要转化邻接矩阵的一半,无向图 { if (G.edge[i][j] != INTMAX && G.edge[i][j] != 0) { edges[k].begin = i; edges[k].end = j; edges[k].weight = G.edge[i][j]; k++; } } } for (i = 0; i < k-1; i++)//简单交换排序 { for (j = i + 1; j < k; j++) { if

克鲁斯卡尔算法

橙三吉。 提交于 2020-02-13 13:54:20
环境: Codeblocks 13.12 + GCC 4.7.1 基本思想 :(1)构造一个只含n个顶点,边集为空的子图。若将图中各个顶点看成一棵树的根节点,则它是一个含有n棵树的森林。(2)从网的边集 E 中选取一条权值最小的边, 若该条边的两个顶点分属不同的树,则将其加入子图 。也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之(3)依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。 大白话 :(1)将图中的所有边都去掉。(2)将边按权值从小到大的顺序添加到图中, 保证添加的过程中不会形成环 (3)重复上一步直到连接所有顶点,此时就生成了最小生成树。这是一种贪心策略。 难点 :判断某条边<u, v>的加入是否会在已经选定的边集集合中形成环。 解决办法 :使用 并查集 ,分别找出两个顶点u, v所在树的根节点。若根节点相同,说明u, v在同一棵树中,则u, v连接起来会形成环;若根节点不同,则u, v不在一棵树中,连接起来不会形成环,而是将两棵树合并。 图解过程:原图如下 边集数组按权值顺序排列 边<1, 2>和<4, 5>在添加到图中的时候形成了环,所以不能将v1和v2,v4和v5连起来。 判断是否成环 int Find(int *parent, int f) { while (

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

不羁岁月 提交于 2020-02-02 14:22:30
普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法 普里姆算法的基本思想: 取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。添加顶点w的条件为:w 和已在生成树上的顶点v 之间必定存在一条边,并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。 最小生成树的构建: 克鲁斯卡尔算法的基本思想: 考虑问题的出发点: 为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。 具体做法: 先构造一个只含 n 个顶点的子图 SG,然后从权值最小的边开始,若它的添加不使SG 中产生回路,则在 SG 上加上这条边,如此重复,直至加上 n-1 条边为止。 最小生成树的构建: 来源: CSDN 作者: zhupengqq1 链接: https://blog.csdn.net/zhupengqq1/article/details/104141689

java--克鲁斯卡尔算法、弗洛伊德算法

一世执手 提交于 2019-12-25 10:25:25
迪杰斯特拉算法 1,应用场景-最短路径问题 2.算法过程 1,设置出发顶点为v,顶点集合为V,v到V的个顶点的距离集合Dis 2,从Dis中选择值最小的di并移出Dis集合,同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径 3,更新Dis,更新规则为:比较v到V集合中顶点的距离值,与v通过vi到V集合中顶点的距离值,保留值较小的一个 4,重复执行,直到最短路径顶点为目标顶点即可结束 public class DijkstraAlgorithm { public static void main ( String [ ] args ) { char [ ] vertex = { 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' } ; //邻接矩阵 int [ ] [ ] matrix = new int [ vertex . length ] [ vertex . length ] ; final int N = 65535 ; //表示不可连接 matrix [ 0 ] = new int [ ] { N , 5 , 7 , N , N , N , 2 } ; matrix [ 1 ] = new int [ ] { 5 , N , N , 9 , N , N , 3 } ; matrix [ 2 ] = new int [ ] { 7 ,

最小生成树(克鲁斯卡尔算法)

老子叫甜甜 提交于 2019-12-02 19:13:58
“本模块关联知识点:并查集” 首先先引入带权无向图的概念 :所谓的带权无向图,就是无向图的边都有权值。 最小生成树即保证每个节点在联通并且没有回路的状态下边的权值之和最小 最小生成树有两种解决方法:1、prime算法;2、kruskal算法;本篇讲解kruskal算法 kruskal算法相较于prime算法更暴力,核心思想是利用快排不断取最小权值的边并通过并查集维护防止产生回路(见下图) 图中最终可得出最小生成树的权值为 2+1+1+1+3=7 代码实现(以 洛谷P3366 为例) 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000) 接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi 输出格式: 输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz 输入输出样例 输入样例 4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3 输出样例 7 本题与上图例题相似,orz输出的判定根据树的节点之间边的数量为节点数-1,这里直接写出实现代码。 #include #include #include #include using namespace std; struct

图算法--克鲁斯卡尔算法

百般思念 提交于 2019-12-02 02:16:45
/* * 克鲁斯卡尔(Kruskal)最小生成树 */ void kruskal(Graph G) { int i,m,n,p1,p2; int length; int index = 0; // rets数组的索引 int vends[MAX]={0}; // 用于保存"已有最小生成树"中每个顶点在该最小树中的终点。 EData rets[MAX]; // 结果数组,保存kruskal最小生成树的边 EData *edges; // 图对应的所有边 // 获取"图中所有的边" edges = get_edges(G); // 将边按照"权"的大小进行排序(从小到大) sorted_edges(edges, G.edgnum); for (i=0; i<G.edgnum; i++) { p1 = get_position(G, edges[i].start); // 获取第i条边的"起点"的序号 p2 = get_position(G, edges[i].end); // 获取第i条边的"终点"的序号 m = get_end(vends, p1); // 获取p1在"已有的最小生成树"中的终点 n = get_end(vends, p2); // 获取p2在"已有的最小生成树"中的终点 // 如果m!=n,意味着"边i"与"已经添加到最小生成树中的顶点"没有形成环路 if (m !

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

一个人想着一个人 提交于 2019-11-30 10:26:05
最小生成树-克鲁斯卡尔算法 算法思想 1.将图的所有连接线去掉,只剩顶点 2.从图的边集数组中找到权值最小的边,将边的两个顶点连接起来 3.继续寻找权值最小的边,将两个顶点之间连接起来,如果选择的边使得最小生成树出现了环路,则放弃该边,选择权值次小的边 4.直到所有的顶点都被连接在一起并且没有环路,最小生成树就生成了。 克鲁斯卡尔算法代码 //在连通网中求出最小生成树 #include <stdio.h> #include <stdlib.h> #define MAXEDGE 20 #define MAXVEX 20 #define INFINITY 65535 typedef struct { int arc[MAXVEX][MAXVEX]; int numVertexes, numEdges;//顶点数,边数 }MGraph; typedef struct { int begin; int end; int weight; }Edge; //对边集数组Edge结构的定义 //创建图的邻接矩阵 void CreateMGraph(MGraph *G) { int i, j; G->numEdges=11; G->numVertexes=7; for (i = 0; i < G->numVertexes; i++) { for ( j = 0; j < G->numVertexes

Kruskal算法 (克鲁斯卡尔)

≡放荡痞女 提交于 2019-11-30 08:36:22
定义 Kruskal算法是一种用来查找最小生成树的算法。 准备 树: 如果一个无向连通图中不存在回路,则这种图称为树。 生成树 : 无向连通图G的一个子图如果是一颗包含G的所有顶点的树,则该子图称为G的生成树。 生成树是连通图的极小连通子图。这里所谓极小是指:若在树中任意增加一条边,则将出现一条回路;若去掉一条边,将会使之变成非连通图。 最小生成树: 对无向连通图的生成树,各边的权值总和称为生成树的权,权最小的生成树称为最小生成树。 构成生成树的准则有三条: ① 必须只使用该网络中的边来构造最小生成树。 ② 必须使用且仅使用n-1条边来连接网络中的n个顶点 ③ 不能使用产生回路的边。 实现 ① 将原图中每条边的权值进行从小到大排序。 ② 从小到大依次判断每条边。 若当前边不会与当前的最小生成树形成回路,则将当前边加入当前的最小生成树。 反之,则放弃该边,继续判断下一条边。 直到选择了(顶点数-1)条边为止,此时的生成树为最小生成树。(一般利用并查集判断是否形成回路) ① 排序 ②从小到大判断每条边。 代码 #include<bits/stdc++.h> using namespace std; struct node { int u,v,w; node(){} node(int a,int b,int c) {u=a;v=b;w=c;} bool operator <(const

Kruskal克鲁斯卡尔算法

非 Y 不嫁゛ 提交于 2019-11-27 19:35:39
克鲁斯卡尔算法依靠两个辅助数组parent[ ] 和edges[ ]. parent[]数组用于实现并查集操作,即查询一个顶点所在集合的根节点,以及将两个集合合并成为一个集合。 edges[]数组作为图中边的集合,其中各个边按照权值大小升序排序,这样克鲁斯卡尔算法只需依次遍历edges[]数组便可依次向树中 添加一个当前权值最小的边,另外借助parent[]数组的查询操作保证加入的边不会造成环。 1 #define MAXSIZE 100; 2 typedef struct{ 3 int a; //a,b为边的两个顶点 4 int b; 5 int weight; //这条边的权值 6 }Edge; //边结构体 7 8 int find(* parent,int a) //查找顶点a的所在集合的根结点 9 { 10 while(parent[a] > 0) //paren数组中根节点的值等于-1 11 a = parent[a]; 12 return a; 13 } 14 int parent[MAXSIZE]; //父亲顶点数组 实现并查集操作 15 Edge edges[MaxEdge]; //边数组 16 17 void Kruskal(MGrahp G) 18 { 19 int i,a,b; 20 sort(deges); //对图中的边按权值大小升序排列 21 for