不相交的森林 - 当两个节点的发现具有相同的等级时,为什么要将等级增加一?

时间:2013-08-06 13:24:07

标签: algorithm data-structures disjoint-sets union-find disjoint-union

我正在实施disjoint-set datastructure来进行联合查找。我在维基百科中看到以下声明:

  

......每当两个相同等级的树r合并时,结果的等级为r + 1。

当树木属于同一级别时,为什么连接树的等级只增加一个?如果我只是添加两个等级(即2*r)会发生什么?

5 个答案:

答案 0 :(得分:7)

首先,排名是什么? 几乎与树的高度相同。事实上,现在,假装它与高度相同。

我们希望保持树木短,所以跟踪每棵树的高度有助于我们做到这一点。当联合两个不同高度的树时,我们使较短树的根成为较高树的根的子。重要的是,这不会改变较高树的高度。也就是说,较高树的等级不会改变。

然而,当联合两个相同高度的树时,我们将一个根作为另一个的子,这会将整个树的高度增加一个,所以我们将该根的等级增加一个。

现在,我说排名几乎与树的高度相同。为何几乎?由于路径压缩,union-find数据结构使用的第二种技术可以保持树的简短。路径压缩可以改变现有树,使其比其等级指示的更短。原则上,根据实际高度做出决策可能比使用等级作为高度代理更好,但在实践中,跟踪真实高度信息太难/太慢,而它很容易/快速跟踪排名。

您还问过“如果我只是添加两个等级(即2 * r)会发生什么?”这是个有趣的问题。答案可能没什么,这意味着一切都会运转得很好,效率和以前一样。 (好吧,假设您使用1作为起始等级而不是0.)为什么?因为使用等级的方式,重要的是等级的相对排序,而不是它们的绝对大小。如果你添加它们,那么你的等级将是1,2,4,8而不是1,2,3,4(或者更可能是0,1,2,3),但它们仍然具有完全相同的相对排序所以一切都很好。你的排名只是2 ^(旧排名)。最大的危险是,当处理非常大的集合时,你会冒更大的溢出用于表示排名的整数的风险(换句话说,你将需要使用更多的空间来存储你的排名)。

另一方面,请注意,通过添加两个等级,您将近似树的大小而不是树的高度。通过始终添加两个等级,无论它们是否相等,那么您正在精确地跟踪树的大小。同样,一切都运行得很好,如果树木非常大,可能会出现溢出整数的可能性。

事实上,按尺寸联合被广泛认为是逐级联盟的合法替代方案。对于某些应用程序,您实际上想知道集合的大小,对于那些应用程序,按大小实际上优先选择逐级联合。

答案 1 :(得分:6)

因为在这种情况下 - 你添加一棵树是一个"子树"另一个 - 这使原始子树的大小增加。

看一下以下示例:

1           3
|           |
2           4

在上面," rank"每棵树都是2。
现在,让我们说1将成为新的统一根,您将获得以下树:

    1
   / \
  /   \
 3     2
 |
 4

加入后排名" 1"是rank_old(1) + 1 - 如预期的那样。 1

至于你的第二个问题,因为它会为树木产生错误的高度。

如果我们采用上面的例子,并合并树来获得等级3的树。如果我们想要将它与这个树合并 2 会发生什么:

         9
        / \
      10   11
            |
           13
            |
           14

我们发现这两个等级都是4,并尝试以与之前相同的方式合并它们,而不是偏向于更短的'树 - 这将导致树高度更高,最终 - 时间复杂度更差。


(1)免责声明:本答复的第一部分取自my answer to a similar question(虽然由于你的问题的最后部分不一致)

(2)请注意,上面的树是合成的,它不能在优化的不相交森林算法中创建,但它仍然展示了答案所需的问题。

答案 2 :(得分:4)

如果您更深入地阅读that paragraph,您会发现rank更像是深度,而不是尺寸:

  

由于树的深度会影响运行时间,因此深度较小的树会添加到较深树的根下,如果深度相等,则只会增加深度。在该算法的上下文中,使用术语“等级”而不是“深度”......

并且相同深度树的合并仅将树的深度增加一,因为一个树的根被添加到另一个树的根。

考虑:

  A                  D
 / \   merged with  / \
B   C              E   F

是:

  A
 /|\
B C D
   / \
  E   F

两者的深度均为2,合并后的深度为3。

答案 3 :(得分:3)

Rank表示树的深度,而不是其中的节点数。当您使用较小等级的树加入具有较大等级的树时,整体等级保持不变。

考虑将等级为4的树添加到等级6的树的根中:因为我们在深度为4的树的根之上添加了一个节点,所以该子树现在的等级为5.我们所在的子树。我们添加了深度为4的树,然而,是6,因此等级不会改变。

现在考虑将等级为6的树添加到等级6的第二个树的根中:因为第一个深度为6的树的根现在上面有一个额外的节点,该子树的等级(以及整个树) )改为7。

由于树的等级决定了处理速度,因此算法通过始终将较短的树附加到较高的树来尝试保持等级尽可能低,从而保持整体等级不变。只有当树木具有相同的等级时,等级才会改变,在这种情况下,其中一个等级附加到另一个的根部,将等级提高一个。

答案 4 :(得分:0)

实际上,我们应该非常了解这两个重要的属性....

1)什么是等级? 2)为什么使用排名???

排名不过是一棵树的深度。您可以说等级是一棵树的深度(级别)。当我们创建并集节点时,这些(图形节点)将形成具有最终根节点的树。仅针对那些根节点表示等级。

A merged with D

最初,A的等级(级别)为0,而D的等级(级别)为0。因此,您可以合并它们,使其中任何一个成为根。因为如果您以A为根,则等级(级别)将为1 如果您以D为根,那么排名也将为1

A
 `D

当root为A时,这里的等级(级别)为1。

现在再想想,

A    merge   B     ----->   A 
 `D           `C           / \
                          D   B
                               \
                                C

因此该级别将增加1,完全没有根(A)的情况下,最大高度/深度/等级为2。等级[1]-> {D,B}和等级[2]-> {C} ................

现在,我们的主要目标是在合并..

时使树的等级(深度)最小。

现在,当两个不同等级的树合并时,

 A(rank 0) merge B(rank 1)---> B  Here merged tree rank is 1 same as high rank (1) 
                  `C          / \
                             A   C

当小排名低于高排名时。然后合并树的等级(高度/深度)将与较高等级树的等级相同。这意味着等级不会增加,合并树等级将与...之前的较高等级相同。

但是,如果我们要进行相反的工作,则意味着高等级树比低等级树要低,然后看,

A ( rank 0 ) merge B  (rank 1 ) --> A   ( merged tree rank 2 greater than both )
                    `C               `B
                                       `C

因此,从下面的观察中可以看到的是,如果我们尝试将合并树的等级(高度)保持为最小,那么我们必须选择第一个过程。我认为这部分很清楚!

现在,您必须了解我们的目标是使树的高度保持最小……。

当我们使用不相交集合并集进行路径压缩(找到与节点连接的最终根)时,当我们从一个节点遍历到其根节点时,如果它的高度(等级)很长,那么处理时间将会很慢。这就是为什么当我们尝试合并两棵树时,我们尝试将heigh / depth / rank保持为最小