Java图论进阶之最小生成树算法详解

yizhihongxing

Java图论进阶之最小生成树算法详解

在图论中,最小生成树(Minimum Spanning Tree, MST) 是连接所有图节点的一棵树,其边的权重和最小。本文将介绍最常见的两种求最小生成树的算法——Prim算法和Kruskal算法。

Prim算法

Prim算法以一个初始节点为起点,每次选择距离该节点最近的未访问节点加入生成树中,直至生成一棵生成树,时间复杂度为O(n^2)。

  1. 节点距离数组初始化为非常大的值,起点距离初始化为0。
  2. 选择未访问节点中距离起点最近的节点并标记为已访问。
  3. 如果当前节点已被访问,则跳过该节点。
  4. 更新距离数组和父节点数组。
  5. 重复步骤2-4,直至所有节点均被访问。

Prim算法实现

以下是Prim算法的Java实现示例:

public static int prim(int[][] graph, int n) {
    int[] dist = new int[n]; // 节点距离数组
    boolean[] visited = new boolean[n]; // 节点是否访问过数组

    Arrays.fill(dist, Integer.MAX_VALUE); // 初始化节点距离为无限大
    dist[0] = 0; // 起点距离初始化为0

    for (int i = 0; i < n - 1; i++) {
        int u = -1;
        for (int j = 0; j < n; j++) {
            if (!visited[j] && (u == -1 || dist[j] < dist[u])) {
                u = j;
            }
        }
        visited[u] = true;
        for (int v = 0; v < n; v++) {
            if (!visited[v] && graph[u][v] != 0 && graph[u][v] < dist[v]) {
                dist[v] = graph[u][v];
            }
        }
    }

    int ans = 0;
    for (int d : dist) {
        ans += d;
    }
    return ans;
}

Kruskal算法

Kruskal算法以所有边构成的集合为初始状态,每次选择权重最小的边加入生成树中,并更新集合,直至生成一棵生成树,时间复杂度为O(mlogm)。

  1. 创建一个空的优先队列,并将图中所有边加入队列。
  2. 初始化并查集。
  3. 从队列中取出最小边。
  4. 如果加入该边不会形成环,则加入生成树中,并更新并查集中的元素。
  5. 重复步骤3-4,直至生成一棵生成树。

Kruskal算法实现

以下是Kruskal算法的Java实现示例:

public static int kruskal(int[][] graph, int n) {
    PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> a[2] - b[2]); // 权重最小的边优先队列

    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (graph[i][j] != 0) {
                queue.offer(new int[]{i, j, graph[i][j]}); // 将图中所有边加入队列
            }
        }
    }

    UnionFind uf = new UnionFind(n); // 初始化并查集

    int ans = 0;
    while (!queue.isEmpty()) {
        int[] edge = queue.poll();
        int u = edge[0], v = edge[1], w = edge[2];
        if (uf.find(u) != uf.find(v)) { // 如果加入该边不会形成环
            ans += w;
            uf.union(u, v);
        }
    }
    return ans;
}

示例说明

假设有以下无向带权图:

     7       2
 A-------B-------C
 |      / \
8|   /     \4
 | /        \
 D-------E---F
      9

邻接矩阵表示为:

    A   B   C   D   E   F
 A  0   7   0   8   0   0
 B  7   0   2   0   4   0
 C  0   2   0   0   0   9
 D  8   0   0   0   9   0
 E  0   4   0   9   0   6
 F  0   0   9   0   6   0

使用Prim算法得到的最小生成树为:

     7       2
 A-------B-------C
          \
          4
           \
            E---F
             6

使用Kruskal算法得到的最小生成树为:

       2           4
 B-------C-------F
 |       |       |
 7       2       6
 |       |       |
 A       E-------D
         9

结论

两种算法的时间和空间复杂度不同,适用于不同情况。Prim算法效率相对较高,适合边比较少的图;Kruskal算法适合边比较多的图。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java图论进阶之最小生成树算法详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java获取文件编码,jsoup获取html纯文本操作

    获取文件编码: 在使用Java查看文件的编码时,可以通过两种方式来获取文件的编码:使用Java内部库获取、使用第三方工具库获取。 使用Java内部库获取文件编码 Java内部库中,提供了获取文件编码的方式:使用InputStreamReader类的getEncoding()方法获取文件编码。以下是示例代码: public static String getF…

    Java 2023年5月19日
    00
  • 关于Java中重定向传参与取值

    关于Java的重定向传参与取值的完整攻略如下: 1. 重定向传参 重定向(Redirect)是指将请求转发到另一个URL上的一种技术。在Java Web开发中,可以使用response.sendRedirect(String url)方法实现重定向。在重定向时,可以将参数传递给目标URL。具体实现步骤如下: 在源页面,使用以下代码进行重定向,并将参数添加到U…

    Java 2023年6月15日
    00
  • Java数组与字符串深入探索使用方法

    Java数组与字符串深入探索使用方法 一、数组 1. 定义 Java数组是一个可以容纳固定数量元素的容器,它可以被认为是一个有序的元素列表。数组中的每个元素都有唯一的索引号来标识它们在数组中的位置。数组可以是任何类型,包括基本类型和引用类型。 2. 声明 在Java中,声明一个数组需要指定如下信息:- 数组的类型:数组中元素的类型(int、double、St…

    Java 2023年5月26日
    00
  • java面试题2020抢先看(够全)

    Java面试题2020抢先看(够全)攻略 了解面试题来源和类型 在准备面试之前,需要了解面试题的来源和类型,以更好地制定复习计划。Java面试题2020抢先看(够全)中的题目类型包括Java基础、多线程、集合框架、JVM等。理解这些题目类型,制定相应的复习计划和重点笔记。 针对不同类型的题目做好准备 各类型面试题的准备方式也有所不同。下面以Java基础题为例…

    Java 2023年5月20日
    00
  • ActiveMQ结合Spring收发消息的示例代码

    ActiveMQ是目前非常流行的一种消息中间件,而Spring框架则是目前最为流行的Java企业应用开发框架之一。它们可以结合使用,为我们带来高效可靠的消息传递。 下面,我将详细讲解如何在Spring中使用ActiveMQ进行消息的发送与接收。 环境准备 在开始使用之前,需要先准备好以下环境。 安装ActiveMQ。 创建一个Maven项目,添加Active…

    Java 2023年5月30日
    00
  • JavaSpringBoot报错“PessimisticLockingFailureException”的原因和处理方法

    当使用Java的Spring Boot框架时,可能会遇到“OptimisticLockingFailureException”和“PessimisticLockingFailureException”错误。这些错误通常是由以下原因之一引起的: 乐观锁或悲观锁失败:如果使用乐观锁或悲观锁时失败,则可能会出现这些错误。在这种情况下,需要查找锁失败的原因并解决它。…

    Java 2023年5月5日
    00
  • java从文件中读取数据的六种方法

    Java从文件中读取数据的六种方法 在Java应用程序中,从文件中读取数据是一个常见的操作。这篇文章将为大家介绍Java读取文件的六种方法,帮助大家学习如何读取文件数据。 方法1:使用 FileInputStream FileInputStream fileInputStream = null; try { File file = new File(&quo…

    Java 2023年5月20日
    00
  • jsp与sql语句的混合使用示例

    下面是关于“JSP与SQL语句的混合使用示例”的攻略: 一、JSP页面中引用SQL语句的示例 在JSP页面中获取数据库中的数据,我们可以使用Java的JDBC或ORM框架,也可以使用JSP的内置对象——JDBC Pool和JSTL标签库来完成。下面是一个简单的示例,它使用的是JDBC Pool和JSTL标签库: 首先,在web.xml文件中配置数据源: &l…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部