克鲁斯卡尔算法

简介: 克鲁斯卡尔算法

公众号merlinsea


  • 问题介绍
  • 已知一个无向带权图,现在希望求出保证这个无向带权图连通性同时是的所有遍的权重之和最小的连通子图。
  • 最小生成树问题介绍
  • 现在有一个无向带权图,请求出这个图的最小生成树。
  • 最小指的是基于原图得到的树的边的权值之和是最小的。
  • 树指的是保证图中所有节点连通的无回路的图。


640.png


  • 算法难点: 如何才能快速判断是否存在回路呢?
  • 并查集的介绍
  • 树是保证所有节点连通且没有回路的极大连通子图,在树中的任意两个节点之间多加入一条边,那么就会产生回路。
  • 并查集就是把这些节点看成一个树,并且采用树的双亲存储,如果我们加入一条新的边,边的两个端点节点都在同一棵树中,那么这两个节点之间加入边就会产生回路。


640.png640.png


  • 克鲁斯卡尔代码实现


public class Main {
    public static void main(String[] args) {
        // {0,1,5}表示j节点0,1之间有一条权重为5的边
        int[][] edges = new int[][]{{0,1,5},{0,2,1},{0,3,2},{1,2,3},{2,3,6},{1,4,4},{2,4,2},{3,4,3}};
        int n = 5;
        Arrays.sort(edges, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                //升序排列,返回正数就发生交换
                return o1[2]-o2[2];
            }
        });
        for(int[] edge : edges){
            System.out.println("["+ edge[0]+" "+ edge[1] + " " + edge[2] +"]");
        }
        System.out.println();
        //树的双亲存储
        int[] tree = new int[n];
        for(int i=0;i<n;i++){
            tree[i] = i;
        }
        List<int[]> result = new LinkedList<>();
        int i = 0;
        // cnt 代表我们选取的边的个数
        int cnt  = 0;
        while(cnt<n-1){
            int a = edges[i][0];
            int b = edges[i][1];
            int aPar = findPar(tree,a);
            int bPar = findPar(tree,b);
            if(aPar != bPar){
                //说明a,b不属于同一棵树 ,因此加入<a,b>边不会产生回路
                result.add(edges[i]);
                //链接 bPar 和 aPar
                tree[aPar] = bPar;
                //选取的边+1
                cnt++;
            }
            i++;
        }
        for(int j=0;j<result.size();j++){
            int[] edge = result.get(j);
            System.out.println("["+ edge[0]+" "+ edge[1] + " " + edge[2] +"]");
        }
    }
    /**
     * 查找双亲节点
     */
    public static int findPar(int[] tree,int k){
        if(tree[k]==k){
            return k;
        }
        tree[k] = findPar(tree,tree[k]);
        return tree[k];
    }
}


  • 算法性能分析
  • 从上面的代码中可以发现,克鲁斯卡尔算法的时间开销主要是sort()排序上,在之前的排序算法中,我们知道排序的最快时间复杂度是O(nlogn),而我们排序其实是对所有的边进行排序的,所以对于边越少的图,越适用于通过克鲁斯卡尔算法生成最小生成树。

  • 最小生成树问题的应用场景
  • 比如村村通路问题:假设有若干个村庄,现在政府需要为这些村子进行修路,现在已经知道了每个村庄相互之间的距离,并且修路的费用成本和路之间的距离成正比关系,问如何修路才能保证个村庄可以相互连通的基础上尽可能让市政的投入的费用最小?


640.png

相关文章
|
4天前
|
机器学习/深度学习 算法 数据挖掘
算法金 | 欧氏距离算法、余弦相似度、汉明、曼哈顿、切比雪夫、闵可夫斯基、雅卡尔指数、半正矢、Sørensen-Dice
**摘要:** 了解9种距离和相似度算法:欧氏距离、余弦相似度、汉明距离、曼哈顿距离、切比雪夫距离、闵可夫斯基距离、雅卡尔指数、半正矢距离和Sørensen-Dice系数。这些算法在机器学习、文本分析、图像处理和生物学等领域各有应用。例如,欧氏距离用于KNN和K-Means,余弦相似度用于文本相似性,汉明距离在错误检测中,曼哈顿距离在数据挖掘,切比雪夫距离在棋盘游戏,闵可夫斯基距离通过调整参数适应不同场景,雅卡尔指数和Sørensen-Dice系数用于集合相似度。每种算法有其优缺点,如欧氏距离对异常值敏感,余弦相似度忽略数值大小,汉明距离仅适用于等长数据。
15 2
算法金 | 欧氏距离算法、余弦相似度、汉明、曼哈顿、切比雪夫、闵可夫斯基、雅卡尔指数、半正矢、Sørensen-Dice
|
11月前
|
监控 算法
转:克鲁斯卡尔算法在文档管理软件中应用使其更加高效
克鲁斯卡尔算法是一种用于解决最小生成树问题的贪心算法。在文档管理软件中,可以将网络节点之间的连接关系抽象为一张图,然后使用克鲁斯卡尔算法来寻找最小生成树,即最小的连接所有节点的路径。
71 0
|
12月前
|
存储 算法 数据可视化
转:电子文档管理系统中应用克鲁斯卡尔算法有什么作用
克鲁斯卡尔算法是一种求解最小生成树问题的算法,其在电子文档管理系统中可以用于优化文档的管理和存储。
54 0
|
存储 算法 数据可视化
转:克鲁斯卡尔算法在电子文档管理系统中的应用
克鲁斯卡尔算法能够找到连接所有节点的最小生成树,从而找到最优解。在电子文档管理系统中,这意味着可以通过算法找到最佳的文档组织方式,提高文档检索的效率和精度。
295 0
|
算法 C++
蓝桥杯(聪明的猴子)克鲁斯卡尔算法最小生成树
蓝桥杯(聪明的猴子)克鲁斯卡尔算法最小生成树
77 0
|
监控 算法
转:克鲁斯卡尔算法在电脑监控软件中的应用
在电脑监控软件中,使用克鲁斯卡尔算法可以帮助管理员更好地了解整个网络的拓扑结构,找出网络中潜在的问题和风险点。
306 0
|
算法
Kruskal算法(克鲁斯卡尔)最小生成树
Kruskal算法(克鲁斯卡尔)最小生成树
114 0
|
2天前
|
机器学习/深度学习 算法 调度
Matlab|基于改进鲸鱼优化算法的微网系统能量优化管理matlab-源码
基于改进鲸鱼优化算法的微网系统能量管理源码实现,结合LSTM预测可再生能源和负荷,优化微网运行成本与固定成本。方法应用于冷热电联供微网,结果显示经济成本平均降低4.03%,提高经济效益。代码包括数据分段、LSTM网络定义及训练,最终展示了一系列运行结果图表。
|
7天前
|
算法 安全 数据库
基于结点电压法的配电网状态估计算法matlab仿真
**摘要** 该程序实现了基于结点电压法的配电网状态估计算法,旨在提升数据的准确性和可靠性。在MATLAB2022a中运行,显示了状态估计过程中的电压和相位估计值,以及误差随迭代变化的图表。算法通过迭代计算雅可比矩阵,结合基尔霍夫定律解决线性方程组,估算网络节点电压。状态估计过程中应用了高斯-牛顿或莱文贝格-马夸尔特法,处理量测数据并考虑约束条件,以提高估计精度。程序结果以图形形式展示电压幅值和角度估计的比较,以及估计误差的演变,体现了算法在处理配电网状态估计问题的有效性。
|
4天前
|
数据采集 存储 算法
基于BP算法的SAR成像matlab仿真
**摘要:** 基于BP算法的SAR成像研究,利用MATLAB2022a进行仿真。SAR系统借助相对运动合成大孔径,提供高分辨率图像。BP算法执行回波数据预处理、像素投影及图像重建,实现精确成像。优点是高精度和强适应性,缺点是计算量大、内存需求高。代码示例展示了回波生成、数据处理到插值显示的全过程。