【问题标题】:Do I have to use a Union Find data structure when implementing Kruskal's algoithm?实现 Kruskal 算法时是否必须使用 Union Find 数据结构?
【发布时间】:2015-12-13 00:10:43
【问题描述】:

从我读到的关于 Kruskal 算法的内容来看,似乎我们必须使用联合查找数据结构。但是为什么我不能只使用一个布尔数组来指示特定顶点是否已添加到 MST 中,而只是检查边的两个顶点是否都没有添加到 MST 中呢? IE。类似这样的东西(这类似于 Java,但是是伪代码,所以它可能无法编译):

public Queue<Edge> getMST(Graph graph) {
  boolean[] visited = new boolean[graph.numVertices()];
  PriorityQueue<Edge> pq = new PriorityQueue<>();
  Queue<Edge> mstPath = new Queue<>();
  pq.addAll(graph.edges());
  while(mstPath.size() < graph.numVertices() - 1 && pq.isNotEmpty()) {
    Edge curr = pq.getMin();
    if (visited[curr.to] && visited[curr.from]) continue; // ignore because both vertices of this edge are in MST
    mstPath.add(curr);
    visited[curr.to] = true;
    visited[curr.from] = true;
  }
  return mstPath;
}

那么我为什么要使用 Union Find 数据结构呢?上面的方法不正确吗?

【问题讨论】:

    标签: algorithm graph


    【解决方案1】:

    Kruskal 算法的工作方式是从一堆不连贯的顶点开始,然后一次添加一条边,直到有一个连接所有顶点的生成树。如果在每一步都添加尽可能便宜的边,则最终生成树的成本将最低。

    因此,您在每个步骤中要做的就是找到可以在不形成循环的情况下添加的最便宜的边缘。为此,您需要快速确定一对顶点是否已连接。如果它们已经连接,则在它们之间添加一条边将引入一个循环。如果它们没有连接,您可以添加边,它将连接图中的两个独立组件。

    最简单的数据结构是有一个数组,为每个顶点存储一个数字,每个不同的数字对应一个不同的连接组件。 (使用布尔值是不够的——一开始每个顶点都有一个组件)。该数组允许您检查两个顶点是否在恒定时间内位于同一组件中,但合并两个组件是 O(N),因为您需要更新其所有元素。 union find 数据结构更聪明一些,可以非常快速地完成这两个操作。


    顺便说一句,也许您将 Kruskal 算法与 Prim 算法混淆了。在 Prim 的算法中,您跟踪一棵树,并且在每一步中,您将一个尚未在树中的顶点添加到树中。

    但即便如此,您的提议也不会真正起作用,因为每当您向树添加一条边时,其中一个顶点在树中,而另一个不在。

    【讨论】:

    • 我找不到使用布尔数组不起作用的示例。如果我将已添加到 MST 的每个顶点视为单个组件(通过在布尔数组中标记它们已访问),那么我永远无法添加会创建循环的边。我能想到的唯一场景是假设我们添加到 MST 的所有顶点都在同一个(也是唯一的)组件中,即图形断开连接 - 即生成森林而不是树......
    • 其实我刚刚发现了一个使用布尔数组会出错的情况,谢谢。
    • 我确实认为这种技术适用于 Prim 的算法,但是是什么让你认为它不起作用?您只需要使用 Prim 构建一棵树,因此您知道所有访问过的顶点都在同一棵树中。
    • 我误读了您的 if 语句。我以为它是在做|| 而不是&amp;&amp;。所以它应该对 Prim 工作正常(当然你的 if 语句会有点不同,因为在 Prim 你循环顶点而不是循环边)
    • 至于您的第一条评论,Kruskal 的工作原理是维护一个跨越森林并添加边缘,直到森林变成一棵树。当你开始时,你有一个零边的森林,每个顶点属于一个单独的组件,当你添加边时,你会合并组件直到只剩下一个。
    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多