最小生成树kruskal算法

article/2025/9/16 10:47:26

最小生成树kruskal算法

    • 概述
    • 算法分析
    • 代码

概述

克鲁斯卡尔 ( K r u s k a l ) (Kruskal) (Kruskal)算法是求连通网的最小生成树的另一种方法。与普里姆 ( P r i m ) (Prim) (Prim)算法不同,它的时间复杂度为 O ( e l o g e ) O(eloge) O(eloge)(e为网中的边数),所以,适合于求边稀疏的网的最小生成树 。

P r i m Prim Prim K r u s k a l Kruskal Kruskal,前者更适合顶点较多的时候使用;后者更适合边较少的时候使用;

算法分析

请添加图片描述

按权值由小到大的顺序排列的编辑是:(各边由起点序号,终点序号,权值表示)

  1. (4,6,30)
  2. (2,5,40)
  3. (4,7,42)
  4. (3,7,45)
  5. (1,2,50)
  6. (4,5,50)
  7. (3,4,52)
  8. (1,3,60)
  9. (2,4,65)
  10. (5, 6, 70)

K r u s k a l Kruskal Kruskal算法思想简单,但是在实现的时候需要考虑防止闭合回路的出现。

我们把属于一条边的两个顶点作为一个集合,通过这样方法就可以防止闭合回路的出现。

如果是同一条边就把两个顶点赋值相同的数值。

使用这样的结构体把数据存储起来 E d g e Edge Edge

typedef struct{ int vex1;  //边的起始顶点 int vex2;  //边的终止顶点 int weight; //边的权值 
}Edge;

收集好图的数据以后,使用递归排序使边以从小到大(权值的的大小)的顺序排好。

这是一个递归排序 ↓ ↓

int fun(Edge arr[],int low,int high){int key;Edge lowx;lowx=arr[low];key=arr[low].weight;while(low<high){while(low<high && arr[high].weight>=key)high--;if(low<high)arr[low++]=arr[high];while(low<high && arr[low].weight<=key)low++;if(low<high)arr[high--]=arr[low];}arr[low]=lowx;return low;} 
void quick_sort(Edge arr[],int start,int end)
{int pos;if(start<end){pos=fun(arr,start,end);quick_sort(arr,start,pos-1);quick_sort(arr,pos+1,end);}
}

调用 K r u s k a l Kruskal Kruskal算法生成最小树

void kruskal(Edge E[],int n,int e)
{ int i,j,m1,m2,sn1,sn2,k,sum=0;int vset[n+1];for(i=1;i<=n;i++) //初始化辅助数组 vset[i]=i;k=1;//表示当前构造最小生成树的第k条边,初值为1 j=0;//E(边集)中边的下标,初值为0while(k<e)//生成的边数小于e时继续循环 {m1=E[j].vex1;m2=E[j].vex2;//取一条边的两个邻接点 sn1=vset[m1];sn2=vset[m2];                           //分别得到两个顶点所属的集合编号 if(sn1!=sn2)//两顶点分属于不同的集合,该边是最小生成树的一条边  {//防止出现闭合回路 printf("V%d-V%d=%d\n",m1,m2,E[j].weight);sum+=E[j].weight;k++;   //生成边数增加 if(k>=n)break;for(i=1;i<=n;i++)    //两个集合统一编号if (vset[i]==sn2)  //集合编号为sn2的改为sn1vset[i]=sn1;}j++;//扫描下一条边 }printf("最小权值之和=%d\n",sum);
}

这个算法中,这部分做的是初始化工作。

	int i,j,m1,m2,sn1,sn2,k,sum=0;int vset[n+1];for(i=1;i<=n;i++) //初始化辅助数组 vset[i]=i;k=1;//表示当前构造最小生成树的第k条边,初值为1 j=0;//E(边集)中边的下标,初值为0

v e s t [ ] vest[ ] vest[]数组用于判断两个顶点是否属于同一个集合。

以权值从小到大的顺序取出每一条边(两个顶点和权值),判断这个边两顶点是否属于同一个集合。如果属于,则取下一条边;否则记录这条最小边,然后统一这条边的两个顶点所属的集合。

   while(k<e)//生成的边数小于e时继续循环 {m1=E[j].vex1;m2=E[j].vex2;//取一条边的两个邻接点 sn1=vset[m1];sn2=vset[m2];                           //分别得到两个顶点所属的集合编号 if(sn1!=sn2)//两顶点分属于不同的集合,该边是最小生成树的一条边  {//防止出现闭合回路 printf("V%d-V%d=%d\n",m1,m2,E[j].weight);sum+=E[j].weight;k++;//生成边数增加 if(k>=n)break;for(i=1;i<=n;i++)    //两个集合统一编号if (vset[i]==sn2)  //集合编号为sn2的改为sn1vset[i]=sn1;}j++;//扫描下一条边 }

代码

#include <stdio.h>
#define MAXE 100
#define MAXV 100
typedef struct{ int vex1;  //边的起始顶点 int vex2;  //边的终止顶点 int weight; //边的权值 
}Edge;
void kruskal(Edge E[],int n,int e)
{ int i,j,m1,m2,sn1,sn2,k,sum=0;int vset[n+1];for(i=1;i<=n;i++) //初始化辅助数组 vset[i]=i;k=1;//表示当前构造最小生成树的第k条边,初值为1 j=0;//E(边集)中边的下标,初值为0while(k<e)//生成的边数小于e时继续循环 {m1=E[j].vex1;m2=E[j].vex2;//取一条边的两个邻接点 sn1=vset[m1];sn2=vset[m2];                           //分别得到两个顶点所属的集合编号 if(sn1!=sn2)//两顶点分属于不同的集合,该边是最小生成树的一条边  {//防止出现闭合回路 printf("V%d-V%d=%d\n",m1,m2,E[j].weight);sum+=E[j].weight;k++;   //生成边数增加 if(k>=n)break;for(i=1;i<=n;i++)    //两个集合统一编号if (vset[i]==sn2)  //集合编号为sn2的改为sn1vset[i]=sn1;}j++;//扫描下一条边 }printf("最小权值之和=%d\n",sum);
}
int fun(Edge arr[],int low,int high){int key;Edge lowx;lowx=arr[low];key=arr[low].weight;while(low<high){while(low<high && arr[high].weight>=key)high--;if(low<high)arr[low++]=arr[high];while(low<high && arr[low].weight<=key)low++;if(low<high)arr[high--]=arr[low];}arr[low]=lowx;return low;} 
void quick_sort(Edge arr[],int start,int end)
{int pos;if(start<end){pos=fun(arr,start,end);quick_sort(arr,start,pos-1);quick_sort(arr,pos+1,end);}
}
int main()
{Edge E[MAXE];int nume,numn;printf("输入顶数和边数:\n");scanf("%d%d",&numn,&nume);for(int i=0;i<nume;i++)scanf("%d%d%d",&E[i].vex1,&E[i].vex2,&E[i].weight);quick_sort(E,0,nume-1);kruskal(E,numn,nume);
}
//INPUT要输入的:
//6 10
//1 2 6
//1 3 1
//1 4 5
//2 3 5
//2 5 3
//3 4 5
//3 5 6
//3 6 4
//4 6 2
//5 6 6

http://chatgpt.dhexx.cn/article/ktjlOC9e.shtml

相关文章

最小生成树:

定义&#xff1a; 将图中的 n 结点用 n-1 条边连接起来&#xff0c;使其各个边的权值之和最小的生成树。 普里姆算法&#xff1a; 从点的角度出发。 1、start 数组的值表示起始点的下标&#xff0c;start 的下标代表目的顶点&#xff1b;lowcost 数组的下标代表目的顶点&…

图——最小生成树

图——最小生成树 1. 基本概念 在一个连通无向图G(V, E)中&#xff0c;对于其中的每条边(u,v)∈E&#xff0c;赋予其权重w(u, v)&#xff0c;则最小生成树问题就是要在G中找到一个连通图G中所有顶点的无环子集T⊆E&#xff0c;使得这个子集中所有边的权重之和w(T) ∑ ( u , …

最小生成树的Kruskal算法-详解

最小生成树的Kruskal算法 一、 什么是最小生成树 1.1 最小生成树定义&#xff1a; 一个有 n 个结点的连通图的生成树是原图的极小连通子图&#xff0c;且包含原图中的所有 n 个结点&#xff0c;并且有保持图连通的最少的边。最小生成树可以用kruskal&#xff08;克鲁斯卡尔&a…

最小生成树(C语言简单实现)

最小生成树 本文参考自《大话数据结构》 一个连通图的生成树是一个极小的连通子图&#xff0c;它含有图中全部的顶点&#xff0c;但只有足以构成一棵树的n-1条边。我们把构造连通网的最小代价生成树称为最小生成树 。 找连通网的最小生成树&#xff0c;经典的有两种算法&#…

最小生成树怎么画?

介绍最小生成树的图形画法~以下图为例&#xff1a; 1、从1开始&#xff0c;以1为顶点画圈。在红色线经过的部分中&#xff0c;可见权重分别为6、1、5&#xff0c;最小权重为1。如下图。 2、以上图中得到的1、3为顶点的图中&#xff0c;继续画线&#xff0c;图为黄色线部分。经过…

最小生成树算法

最小生成树算法 生成树的概念最小生成树算法Prim算法Kruskal算法 生成树的概念 若图是连通的无向图或强连通的有向图&#xff0c;则从其中任一顶点出发&#xff0c;调用一次 d f s dfs dfs或者 b f s bfs bfs后&#xff0c;可以系统的访问图中所有顶点。若图是有根的有向图 &a…

【图】最小生成树

最小生成树&#xff1a;构造连通网的最小代价生成树。 最小生成树有两种算法&#xff1a;普利姆算法、克鲁斯卡尔算法。 普利姆&#xff08;Prim&#xff09;算法 加点&#xff0c;选择相邻点中边权最小的 需要两个一维数组&#xff0c;一个存权值&#xff0c;另一个存起始点…

最小生成树-Kruskal算法

数据结构:最小生成树-Kruskal算法 什么是最小生成树&#xff0c;最小生成树就是求图中把所有点都访问到的最短路径的长度 Kruskal算法采用的是边贪心思想&#xff0c;我们先大概讲一下它的大概思想&#xff0c;首先我们先假设先隐藏所有的边&#xff0c;这样每个点会成为一个连…

最小生成树(kruskal算法)

一、概述 最小生成树问题顾名思义&#xff0c;概括来说就是路修的最短。 接下来引入几个一看就明白的定义&#xff1a; 最小生成树相关概念&#xff1a; 带权图&#xff1a;边赋以权值的图称为网或带权图&#xff0c;带权图的生成树也是带权的&#xff0c;生成树T各边的权值…

最小生成树、最短路径树

一、最小生成树与最短路径树的区别 最小生成树能够保证整个拓扑图的所有路径之和最小&#xff0c;但不能保证任意两点之间是最短路径。 应用如网络部线&#xff0c;把所有的电脑(服务器&#xff1f;&#xff09;都连起来用的网线(光纤&#xff1f;&#xff09;最少&#xff0c…

【图解算法】最小生成树

今天我们介绍图论中的另一部分&#xff0c;最小生成树。 对图的最短路感兴趣的同学可以看&#xff1a; 【图解算法】一次解决最短路径问题 目录 1. 最小生成树简介2. Prim算法2.1 模板题2.2 思路模板2.3 代码实现2.3 prim 算法的优化 3. Kruskal算法3.1 模板题3.2 思路模板3.3…

数据结构—最小生成树

目录 一、生成树 二、最小生成树&#xff08;代价最小树&#xff09; 三、求最小生成树 1、Prim算法&#xff08;普里姆&#xff09; 2.Kruskal 算法&#xff08;克鲁斯卡尔&#xff09; 3.Prim算法和Kruskal算法对比 一、生成树 连通图的生成树是包含图中全部顶点的一个…

最小生成树详解

目录 最小生成树简介 什么是树 什么是生成树 什么是最小生成树 最小生成树的做法 Kruscal&#xff08;克鲁斯卡尔&#xff09;算法 思路 代码 其他算法 最小生成树简介 什么是树 树&#xff08;tree&#xff09;是一种特殊的图&#xff0c;一个图要成为树要满足三个条…

最小生成树的实现(C语言)

今天做洛谷的时候刷到好多图论的题&#xff0c;发现自己在这一方面算法的掌握还是有待提高啊。在这就先介绍最小生成树的算法吧。 最小生成树 最小生成树&#xff08;minimum spanning tree&#xff09;是由n个顶点&#xff0c;n-1条边&#xff0c;将一个连通图连接起来&…

详解: 最小生成树

详解: 最小生成树算法 最小生成树&#xff08;Minimum Spanning Tree, MST&#xff09;是在一个给定的无向图G(V, E)中求一棵树&#xff0c;使得这棵树有图G的所有顶点&#xff0c;且所有边都来自图G中的边&#xff0c;并且满足整棵树的边权之和最小. 最下生成树满足如下性质…

最小生成树

目录 一、最小生成树定义&#xff1a; 二、普里姆算法&#xff08;Prim&#xff09; 三、Kruskal算法&#xff08;克鲁斯卡尔&#xff09; 小结&#xff1a; 下一篇&#xff1a;最短路径算法 问题&#xff1a; 一、最小生成树定义&#xff1a; 对于一个带权连通无向图G(V,E)&am…

最小生成树——Prim算法(详细图解)

目录 最小生成树的概念 经典题目 prim算法简介 prim算法解析 &#xff08;详细图解&#xff09; 代码实现 代码实战 最小生成树的概念 在一给定的无向图G (V, E) 中&#xff0c;(u, v) 代表连接顶点 u 与顶点 v 的边&#xff0c;而 w(u, v) 代表此的边权重&#xff0c;若…

最小生成树入门(图解)

1.什么是最小生成树 来看百度百科的定义 一个有 n 个结点的连通图的生成树是原图的极小连通子图&#xff0c;且包含原图中的所有 n个结点&#xff0c;并且有保持图连通的最少的边。最小生成树可以用kruskal&#xff08;克鲁斯卡尔&#xff09;算法或prim&#xff08;普里姆&am…

最小生成树(Prim、Kruskal)算法,秒懂!

前言 在数据结构与算法的图论中&#xff0c;(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法。但是可能很多人对概念不是很清楚&#xff0c;什么是最小生成树? 一个有 n 个结点的连通图的生成树是原图的极小连通子图&#xff0c;且包含原图中的所有 n 个结点&…

最小生成树详解(模板 + 例题)

作为一个伪ACMer,先来首广为人知的打油诗: 模拟只会猜题意&#xff0c;贪心只能过样例&#xff0c;数学上来先打表&#xff0c;规律一般是DP&#xff0c;组合数学碰运气&#xff0c;计算几何瞎暴力&#xff0c;图论一顿套模板&#xff0c;数论只会GCD,递归递推伤不起&#xff0…