关于联合:不相交集的链表表示 – 算法简介文本中的遗漏?

Linked-list representation of disjoint sets - omission in Intro to Algorithms text?

我的上一个 CLRS 问题取得了成功,这是另一个问题:

算法导论,第二版,p。 501-502,描述了不相交集的链表表示,其中每个列表成员维护以下三个字段:

  • 集合成员
  • 指向 next 对象的指针
  • 返回第一个对象的指针(集合 representative)。

虽然链表可以通过仅使用单个"Link"对象类型来实现,但教科书显示了一个辅助"Linked List"对象,其中包含指向"head"链接的指针和"尾"链接。拥有指向"tail"的指针有助于 Union(x, y) 操作,因此无需遍历较大集合 x 中的所有链接即可开始将较小集合 y 的链接附加到它.

然而,为了获得对尾部链接的引用,似乎每个链接对象都需要维护第四个字段:对链接列表辅助对象本身的引用。在这种情况下,为什么不完全删除 Linked List 对象并使用第四个字段直接指向尾部?

您会认为这是文本中的遗漏吗?


1
why not drop the Linked List object entirely and use that fourth field to point directly to the tail?

可以从路径压缩中获得见解。那里的所有元素都应该指向列表的头部。如果它没有发生,那么 find-set 操作就会这样做(通过更改 p[x] 并返回它)。你同样谈到尾巴。所以只有实现了这样的功能,我们才能使用它。


我刚刚打开文本,教科书的描述对我来说似乎很好。

据我了解,数据结构类似于:

1
2
3
4
5
6
7
8
9
10
struct Set {
    LinkedListObject * head;
    LinkedListObject * tail;
};

struct LinkedListObject {
    Value set_member;
    Set *representative;
    LinkedListObject * next;
};

我的书(第二版)中没有提到任何"辅助"链表结构。能贴出相关段落吗?

做一个联合会是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// No error checks.
Set * Union(Set *x, Set *y) {

    x->tail->next = y->head;    
    x->tail = y->tail;

    LinkedListObject *tmp = y->head;

    while (tmp) {

        tmp->representative = x;
        tmp = tmp->next;

    }
    return x;
}