【问题标题】:merging sets which have even one element in common [duplicate]合并甚至有一个共同元素的集合[重复]
【发布时间】:2012-08-21 21:48:01
【问题描述】:

可能重复:
Python: simple list merging based on intersections

我正在尝试对对象进行分类。每个对象都由一个名为id 的唯一标识符属性标识。所以我的分类逻辑是这样的。首先我准备一个对象列表,然后分类函数一次获取 2 个对象并返回一个包含它们的 idfrozenset。因此,如果 object1object5 属于同一类别,则返回 frozenset(id1,id5)。现在我不断将这些frozensets添加到一个集合中,所以最后我有一个这样的集合

matched_set=(
             frozenset(id1,id2),
             frozenset(id9,id3),
             frozenset(id9,id2),
             frozenset(id24,id22),
             frozenset(id1,id23),
             frozenset(id25,id24),
             frozenset(id30,id24)
            )

现在因为id1id2的对象属于同一类别,id9id3的对象属于同一类别,id9id2的对象属于同一类别,带有id1,id2,id3,id9 的对象应该属于同一类别。所以我应该有这样一套set(id1,id2,id3,id9) 有人可以提供这样做的算法吗? 谢谢

【问题讨论】:

标签: python algorithm set


【解决方案1】:

听起来您正在寻找disjoint-set datastructure

鉴于您的 id 集,您的类别将它们分成不相交的子集。不相交集数据结构通过选择一个代表 id 来表示每个类别,该 id 将由对其任何成员的查询返回。 (孤立的 id 形成一个类别,并返回自己)

对不相交集数据结构的更新结合了任何两个 id 的类别,以便将来的查询为两个子集的成员返回相同的代表。 (如果两个 id 已经是同一类别的成员,则更新在功能上是无操作的)

通常的方法是将每个类别表示为一个反向树:每个 id 都有一个parent 链接,但没有子链接。 “代表元素”是树的根,通过跟随父链接很容易查询。更新需要找到两个 id 的树的根,并且(如果它们不同)通过使一个根成为另一个根的父级来合并这些树。

通过添加一些简单的优化(查询“折叠”查询路径以直接指向根,并且更新总是选择最深树的根作为合并父级),这个算法变得非常高效,运行在“几乎-O(1)" 摊销时间。

如果您想在线访问每个类别中的完整 id 列表,您应该维护一个附加到每个类别根的累积列表,并在每次合并中将它们连接起来。一般来说,以这种方式维护任意数量的关于您的类别的统计信息会很方便。

【讨论】:

  • +1 很抱歉破坏了你的 6666 分数 :)
  • 呵呵,我也有同感 8^)
  • 确实非常高效!请参阅stackoverflow.com/a/12064803/567292 了解我的实现,它击败了那里建议的所有其他内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 2019-09-12
  • 2011-10-28
  • 1970-01-01
相关资源
最近更新 更多