【发布时间】:2011-05-28 18:47:36
【问题描述】:
我正在尝试实现用于 Kruskal 算法的不相交集,但我无法准确理解它应该如何完成,尤其是如何管理森林。在阅读了 Wikipedia 对 Disjoint Sets 的描述并阅读了 Introduction to Algorithms (Cormen et al) 中的描述之后,我得出以下结论:
class DisjointSet
{
public:
class Node
{
public:
int data;
int rank;
Node* parent;
Node() : data(0),
rank(0),
parent(this) { } // the constructor does MakeSet
};
Node* find(Node*);
Node* merge(Node*, Node*); // Union
};
DisjointSet::Node* DisjointSet::find(DisjointSet::Node* n)
{
if (n != n->parent) {
n->parent = find(n->parent);
}
return n->parent;
}
DisjointSet::Node* DisjointSet::merge(DisjointSet::Node* x,
DisjointSet::Node* y)
{
x = find(x);
y = find(y);
if (x->rank > y->rank) {
y->parent = x;
} else {
x->parent = y;
if (x->rank == y->rank) {
++(y->rank);
}
}
}
我很确定这是不完整的,而且我遗漏了一些东西。
Introduction to Algorithms 提到应该有一片森林,但它没有对这个森林的实际实现给出任何解释。我观看了 CS 61B 第 31 讲:不相交集 (http://www.youtube.com/watch?v=wSPAjGfDl7Q),这里讲师仅使用一个数组来存储森林及其所有树和值。没有像我提到的那样明确的“节点”类型的类。我还找到了许多其他来源(我不能发布多个链接),它们也使用了这种技术。我很乐意这样做,除了这依赖于数组的索引进行查找,并且由于我想存储非 int 类型的值,我需要使用其他东西(想到 std::map)。
我不确定的另一个问题是内存分配,因为我使用的是 C++。我正在存储指针树,我的 MakeSet 操作将是: new DisjointSet::Node; .现在,这些节点只有指向它们父母的指针,所以我不知道如何找到树的底部。我将如何遍历我的树以将它们全部释放?
我了解这个数据结构的基本概念,但我对实现有点困惑。欢迎任何意见和建议,谢谢。
【问题讨论】:
-
检查一下,看看你缺少什么emilstefanov.net/Projects/DisjointSets.aspx
-
该示例使用静态对象,如果您想使用动态内存管理,请使用 new 和 delete (cplusplus.com/doc/tutorial/dynamic)
标签: c++ disjoint-sets