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

}
相关推荐
艾莉丝努力练剑3 分钟前
【LeetCode&数据结构】单链表的应用——反转链表问题、链表的中间节点问题详解
c语言·开发语言·数据结构·学习·算法·leetcode·链表
武子康1 小时前
Java-72 深入浅出 RPC Dubbo 上手 生产者模块详解
java·spring boot·分布式·后端·rpc·dubbo·nio
_殊途2 小时前
《Java HashMap底层原理全解析(源码+性能+面试)》
java·数据结构·算法
椰椰椰耶3 小时前
【Spring】拦截器详解
java·后端·spring
没有bug.的程序员4 小时前
JAVA面试宝典 - 《MyBatis 进阶:插件开发与二级缓存》
java·面试·mybatis
没有羊的王K5 小时前
SSM框架学习——day1
java·学习
珊瑚里的鱼5 小时前
LeetCode 692题解 | 前K个高频单词
开发语言·c++·算法·leetcode·职场和发展·学习方法
又菜又爱coding5 小时前
安装Keycloak并启动服务(macOS)
java·keycloak
不知道叫什么呀5 小时前
【C】vector和array的区别
java·c语言·开发语言·aigc
wan_da_ren6 小时前
JVM监控及诊断工具-GUI篇
java·开发语言·jvm·后端