Java版-图论-最小生成树-Kruskal算法

实现描述

为了造出一棵最小生成树,我们从最小边权的边开始,按边权从小到大依次加入,如果某次加边产生了环,就扔掉这条边,直到加入了 n-1 条边,即形成了一棵树。

实现代码

  1. 首选我们对所有的边,按照权重排序;
  2. 之后,从小到大选择边,如果当前的边已经连通过了,则放弃此边,查看下一条边;若没有连通过,通过并查集进行连通;
  3. 直至所有点都访问过,此时,完成。

如上图,节点0~5,边关系如上;

先对边权重进行从小到大排序,得到:

java 复制代码
[{
	"u":4,
	"v":5,
	"weight":1
},{
	"u":0,
	"v":5,
	"weight":3
},{
	"u":1,
	"v":2,
	"weight":4
},{
	"u":0,
	"v":1,
	"weight":5
},{
	"u":2,
	"v":3,
	"weight":5
},{
	"u":3,
	"v":4,
	"weight":5
},{
	"u":3,
	"v":5,
	"weight":6
},{
	"u":0,
	"v":3,
	"weight":7
},{
	"u":0,
	"v":2,
	"weight":8
},{
	"u":2,
	"v":5,
	"weight":9
}]

然后依次选择排序后的边:

下面代码对应上图数据及其过程:

java 复制代码
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class kruskal {

    /**
     * 边定义
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class Edge implements Comparable<Edge> {
        int u, v;
        int weight;

        @Override
        public int compareTo(@NotNull Edge o) {
            return weight - o.weight;
        }
    }


    static List<Edge> getKruskalEdges(int nodeNum, int[][] grid) {
        List<Edge> result = new LinkedList<>();
        List<Edge> edges = new LinkedList<>();
        for (int i = 0; i < grid.length; i++) {
            int u = grid[i][0];
            int v = grid[i][1];
            int weight = grid[i][2];
            edges.add(new Edge(u, v, weight));
        }
        Collections.sort(edges);
        UnionFindTemplate uf = new UnionFindTemplate(nodeNum);
        Set<Integer> visited = new HashSet<>();
        for (Edge edge : edges) {
            if (uf.connected(edge.u, edge.v)) {
                continue;
            }
            uf.union(edge.u, edge.v);
            visited.add(edge.u);
            visited.add(edge.v);
            result.add(edge);
            if (visited.size() == nodeNum) {
                break;
            }
        }
        return result;
    }



    public static void main(String[] args) {
        int nodeNum = 6;
        int[][] grid = {
                {0, 1, 5},
                {0, 5, 3},
                {0, 3, 7},
                {0, 2, 8},
                {1, 2, 4},
                {2, 5, 9},
                {3, 5, 6},
                {2, 3, 5},
                {3, 4, 5},
                {4, 5, 1}
        };
        System.out.println(JSONObject.toJSONString(getKruskalEdges(nodeNum, grid)));
    }
}

其中,并查集模版的实现如下:

java 复制代码
public class UnionFindTemplate {
    int[] parent;
    int[] size;
    int n;
    public int setCount;//连通分量个数

    public UnionFindTemplate(int n) {
        this.n = n;
        this.parent = new int[n];
        this.size = new int[n];
        setCount = n;
        Arrays.fill(this.size, 1);
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
        }
    }

    public int findParent(int x) {
        if (parent[x] == x) {
            return x;
        } else {
            parent[x] = findParent(parent[x]);
            return parent[x];
        }
    }

    public void union(int x, int y) {
        x = findParent(x);
        y = findParent(y);
        if (x == y) {
            return;
        }
        if (size[x] < size[y]) {
            int temp = x;
            x = y;
            y = temp;
        }
        //y合并到x
        parent[y] = x;
        size[x] += size[y];
        setCount--;
    }

    public boolean connected(int x, int y) {
        x = findParent(x);
        y = findParent(y);
        return x == y;
    }

}
相关推荐
ym hyd 1114 小时前
试题库管理系统源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·毕设
AC赳赳老秦4 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
钱栈up4 小时前
mvn compile 卡死在 javac 阶段:一次类型不匹配的排查与修复
java·开发语言
吠品6 小时前
CSS图片模糊过渡:一个transition加filter就够
java·数据库·notepad++
朝朝辞暮i6 小时前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法
步行cgn6 小时前
Spring 全注解开发详解
java·后端·spring
青梅橘子皮6 小时前
Blue---二分算法(二分查找与二分答案)
算法
长河7 小时前
Java的GC(垃圾回收)中,标记无用对象的核心方法是可达性分析算法
java·jvm·算法
code2cat7 小时前
Java进阶篇之LongAdder:把统计更新分散,再读取总和
java·并发编程·原子类·longadder
月光船幽幽7 小时前
加性偏移外推提升参数识别可靠性
python·算法