不相交设置数据结构和二叉树?

时间:2012-12-12 21:56:54

标签: algorithm data-structures binary-tree disjoint-sets binomial-heap

有人可以解释一下Disjoint Sets Data Structure是什么吗?或者将我链接到一个YouTube视频或解释得很好的文章。

我几分钟前搜索过它,我得到的只是一些数学课程,其中包含一个看起来像维恩图的图像。也许就是这样,但我不确定,所以任何帮助都会受到赞赏。

快速注意,当我被问到“如何使用二叉树来表示二项式队列中的每个二叉树时”这是指你必须相互堆叠的二叉树。就像B1附加一个B1成为B2,那么两个B2成为B3,依此类推。

3 个答案:

答案 0 :(得分:5)

不相交集数据结构是用于表示partition of a set S的数据结构。您从一组元素开始,每个元素属于它自己的组。例如:

{1} {2} {3} {4} {5} {6}

对不相交集数据结构的一个操作是 union 操作,它将包含给定元素的两个集合组合在一起。例如,将1和2合并在一起会返回分区

{1, 2} {3} {4} {5} {6}

联合3和5产生

{1, 2}, {3, 5}, {4}, {6}

现在,将1和3合并在一起会产生分区

{1, 2, 3, 5}, {4}, {6}

find 操作会告诉您给定元素属于哪个集合。通常,这是通过让find返回它所属元素的代表元素来完成的。这通常是这样做的

find(x) == find(y)  if and only if  x and y are in the same set.

例如,find(1)可能返回2,因此find(2)= 2,find(3)= 2,find(5)= 2.

不相交集数据结构通常用作Kruskal最小生成树算法中的子例程,因为它们提供了一种非常快速的方法来检查图中的两个节点是否已连接,以及一种标记两个连接组件中所有节点的简单方法当添加边缘时,它们彼此连接。使用 disjoint-set forest 实现并逐级联合和路径压缩,可以在O(nα(n))时间内对不相交的林进行n次操作,其中α( n)是inverse Ackermann function,一个生长得如此缓慢的函数它实际上是一个常数(对于任何小于宇宙大小的输入,它最多为四个。)


对于二叉树和二叉树:我认为你要问的是如何使用二叉树来表示二叉树,这是多路树,最多只有两个孩子。并非所有二叉树都是二叉树,因此必须使用合适的编码。

执行此操作的一种方法是使用称为left-child right-sibling表示的内容。根据以下设置,这表示多路树为二叉树:

  • 每个节点的子节点指向节点的第一个子节点。
  • 每个节点的子节点指向其下一个兄弟节点(同一层中具有相同父节点的节点)。

例如,给定这个二叉树:

     a
   / | \
  b  c  d
 /|  |
e f  g
  |
  h

左子右兄弟代表将是

                 a
                /
               b
            /    \
           e      c
            \    / \
             f  g   d
            /
           h   

顺便说一下 - 如果你在二叉树上这样做,你最终会得到一个二叉树的表示,称为半有序半树,这是一个带有二叉树的二叉树。以下属性:

  • 树中的每个节点都大于或等于(或小于或等于,取决于这是最小堆还是最大堆)其左子树中的每个节点。
  • 根节点没有正确的孩子。

这些定义遵循以下事实:二叉树是堆排序的,然后转换为左子右兄弟表示。使用此表示法,将二叉树连接到二叉树是非常快的。我将把它作为练习留给读者。 : - )

希望这有帮助!

答案 1 :(得分:1)

Disjoint set基本上是一个联合查找数据结构。

您最初拥有一组n个节点,并且您有 find(node) union(node1,node2) 操作。

  • union(node1,node2)正在将节点“合并”为一组
  • find(node)正在找到node的标准表示 给出根,例如,如后面解释的那样)

例如,您最初拥有{1},{2},{3},{4},{5},并执行:

union(1,2)
union(3,4)

然后你最终得到{1,2},{3,4},{5}
这也意味着此时find(1) == find(2)(它是同一套!)

如果您稍后union(2,3) - 它将导致将包含2的 set 与包含3的 set 结合起来,最终会得到{{1 }}

关于视频请求This lecture from Berkley似乎很好地涵盖了这些材料。


关于二叉树 - 它是一种实现方式,每个“根”都有它的子,但树实际上是“倒置”,而不是从父亲到儿子的指针,你有从儿子到父亲的指针。
这样,每个节点的正典表示就是节点通向的根,这确保了如果我们在{1,2,3,4},{5}a上进行联合,那么b ,因为他们有相同的根。

我希望它可以为您提供有关此DS的一些信息。 祝你好运!

答案 2 :(得分:1)

我在大学学到的不相交的集合围绕着三个基本功能。

make_set(x) - makes a new disjoint contains only the element x
find_set(x) - gives you the set that contains element x
union(x,y) - unions the sets that contain x and y

他们提到的实施是链接列表。也就是说,每个集合都具有创建集合的元素的代表。 (make_set(x))然后使用unions(x,y)x的结束指针移动到指向yUnionmake_set速度很快但find_set的速度非常慢(实际上是O(最大集合))

更好的实现使用了两个名为 path compression 的方法,它作为一个元素与union和/或find_set一起传递,它使它指向代表集合

另一个,按排名结合,它为每个集合维持一个等级,给出了该集合的最大“深度”。当联合时,如果每组的等级相同,则它将一个加到等级中,一个代表被改为指向另一个。如果它们不同,那么较小的集合被改变为指向较大的代表并且等级保持不变。这个渐近上界非常接近于函数的使用次数。

希望有所帮助。