不相交集合的联盟

时间:2014-12-30 18:39:22

标签: merge hashtable union-find

我正在研究支持国际电联职能的脱节集。

树的高度减少技术:

我们总是将较小的树合并为较大的树,即我们使较小的树的根指向较大树的根。

如果树有更多节点,则树大于其他树。

每个节点都是一个带有字段的结构:元素的一些信息,父节点的指针“父”和计数器“count”,仅当节点是根并包含数字时才使用上树的节点。

以下算法合并了两棵树:

pointer UpTreeUnion(pointer S,T) {
   if (S == NULL OR P == NULL) return;
   if (S->count >= T->count) {
       S->count = S->count + T->count;
       T->parent = S;
       return S;
   }
   else {
       T->count = T->count + S->count;
       S->parent = T;
       return T;
   }
}

考虑使用union的不相交集的实现,其中最多可以有k个不相交集。 该实现使用散列表A [0..max-1],在该散列表中存储基于有序双散列方法的密钥。 设h1和h2分别为主要和次要散列函数。 A包含所有上述树的节点的键,并且还包含指向每个树的相应节点的指针。 我想编写一个算法,该算法将两个节点的键作为参数进行合并,并合并节点所属的向上树(节点可以属于任何向上的树,即使在相同的情况下也是如此,它看起来是合适的消息) 。在合并时,我们应该应用路径压缩和高度降低的技术。

你能否给我一个暗示我们如何做到这一点?

假设我们有这个数组:

enter image description here

一开始,节点将是这样的:

enter image description here

然后,如果k1 = 100,k2 = 5,那么在应用算法之后,我们会得到这个吗?

enter image description here

然后,如果我们有k1 = 59,k2 = 5,我们将得到以下结果:

enter image description here

右?然后应用路径压缩,我们开始这样做:

tmp=B
while (B->parent!=B)
      parent=B->parent;
      tmp->parent=B;
      tmp=parent;
}

所以我们将父= F,tmp-> gt; parent = B,tmp = F.

我们如何继续?

然后k1 = 14,k2 = 59我们得到这个:

enter image description here

1 个答案:

答案 0 :(得分:2)

首先,当你获得密钥时,你需要在哈希表中找到它们 哈希表包含条目:(key, pointer-to-node)
我们假设你想找到关键k。你检查:
A[h1(k) + 0*h2(k) mod size(A)] - 如果它包含密钥k,则会读取相应的指向节点的指针 如果还有k以外的其他内容,请检查:
A[h1(k) + 1*h2(k) mod size(A)]
A[h1(k) + 2*h2(k) mod size(A)]
A[h1(k) + i*h2(k) mod size(A)] ...直到找到关键k

现在您有指向2个节点的指针,您需要找到这些节点所属的树的根。要找到根,您可以上到树,直到到达根节点。您可以为每个节点使用parent指针,例如,您可以假设根parent指针指向自身。

现在您有2个根,可以使用upTreeUnion合并它们。

路径压缩的工作原理如下:

enter image description here

找到节点s的树根后,再次按照从s到root的路径,并将路径上每个节点的parent指针设置为根

<强>更新

Algorithm(k1,k2){
   int i=0,j=0;
   int i1,i2;
   while (i<max and A[i1 = h1(k1)+i*h2(k1) mod size(A)]->key!=k1){
          i++;
   }
   while (j<max and A[i2 = h1(k2)+j*h2(k2) mod size(A)]->key!=k2){
          j++;
   }
   if (A[i1]->key!=k1) return;
   if (A[i2]->key!=k2) return;

   pointer node1,node2,root1,root2;
   node1=A[i1]->node;
   node2=A[i2]->node;
   root1=UpTreeFind(node1);
   root2=UpTreeFind(node2);
   if (root1==root2){
      printf("The nodes belong to the same up tree");
      return;
   }

   // path compression
   pointer tmp,tmpParent;

   tmp = node1;
   while (tmp->parent!=root1) {
       tmpParent=tmp->parent;
       tmp->parent=root1;
       tmp=tmpParent;
   }

   tmp = node2;
   while (tmp->parent!=root2) {
       tmpParent=tmp->parent;
       tmp->parent=root2;
       tmp=tmpParent;
   }

   UpTreeUnion(root1,root2);
}