繁体   English   中英

Kruskal 的算法能否以这种方式实现,而不是使用不相交集的森林?

[英]Could Kruskal’s algorithm be implemented in this way instead of using a disjoint-set forest?

我正在从这篇 geeksforgeeks 文章中学习 Kruskal 的 MST。 给出的步骤是:

  1. 按重量的非递减顺序对所有边进行排序。

  2. 选择最小的边。 检查它是否与到目前为止形成的生成树形成一个循环。 如果未形成环,则包括此边。 否则,丢弃它。

  3. 重复步骤(2),直到生成树中有(V-1)条边。

我真的觉得没有必要使用不相交的集合。 为了检查循环,我们可以将顶点存储在访问数组中,并在选择边时将它们标记为真。 循环遍历程序,如果我们找到一条边,其两个顶点都在访问数组中,我们将忽略该边。

换句话说,不是存储一个不相交集的森林,我们不能只存储一个位数组来指示哪些顶点在之前的某个步骤中已链接到另一条边?

我真的不需要使用不交集。 代替检查周期,我们可以将顶点存储在访问数组中,并在选择边时将其标记为true。 如果我们找到一条两条顶点都位于访问数组中的边,则在程序中循环,我们将忽略该边。

是的,您当然可以做到。 在该算法中使用不交集的重点是性能 与使用List相比,使用合适的不相交集实现可产生更好的渐近性能。

您所描述的方法在所有情况下均无法正常工作。 例如,考虑以下折线图:

A - - B - - C - - D

假设AB的权重为1,CD的权重为2,B-C的权重为3。Kruskal的算法在此做什么? 首先,它将添加A-B,然后添加C-D,然后添加B-C。

现在想象一下您的实现会做什么。 当我们添加A-B时,您会将A和B标记为已访问。 然后,当我们添加C-D时,您将C和D标记为已访问。 但是,当我们尝试添加B-C时,由于同时访问了B和C,因此您将决定不添加边,从而留下未连接的结果。

这里的问题是,在建立MST时,您可能会添加链接过去已链接到其他节点的节点的边。 因此,添加边缘的标准是“这些节点之前已经链接过吗?”较少,而更多的是“这些节点之间已经存在路径了吗?”,这就是不交集的森林出现的地方。

戳破和推动常规实现,并试图找到改进方法的做法真是太好了。 如果您这样做的话,您将学到很多有关这些算法的知识! 在这种情况下,恰好发生了您所提议的内容行不通的情况,而了解其为何行不通的情况有助于您弄清现有方法为何如此。

您的困惑可能来自第2步,其措词不正确。

它说:“检查它是否与迄今为止形成的生成树一起形成一个循环。”,但到目前为止所形成的不是生成树。 这是一个由不连贯的生成树和一些未访问的顶点组成的森林

在林中找到连接两个不同生成树的边时,算法将失败。 这些顶点将在以前访问过,但是边缘不会循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM