【问题标题】:Persistent Union-Find with occasional removalsPersistent Union-Find 偶尔删除
【发布时间】:2018-12-16 20:05:35
【问题描述】:

我有一组半百万的项目存储在数据库中,需要以下操作:

  • union(x, y) 就像在 Union-Find 中一样
  • findAll(x) 查找所有 y 使得 find(x) == find(y)
  • ununion(x, y) 恢复以前的联合操作

这是一个实际问题,已知如下

  • 分区通常很小(少于 100 个元素),但不能保证。
  • union 操作的速度并不重要。
  • findAll 必须快速并且需要在 SQL 中实现(没有递归/CONNECT BY)。
  • 有时,我们发现某些union 实际上是错误的,需要撤消它,同时保留所有之前和之后的unions。这种操作很少见,所以速度无关紧要。
  • findAll 没有必要立即看到其他操作所做的更改。一些后处理就可以了。

经典的 Union-Find 算法需要路径压缩(或变体)以提高效率,并且不允许删除边(即使没有路径压缩)。我知道Dynamic connectivity,但它似乎不适用于我的用例。

我想,我们不能使用它,因为findAll 的速度是最重要的。可能,我们应该将所有节点直接链接到根。

关于ununion,我唯一的想法是单独存储所有union操作,并在ununion上,从相应分区中删除所有链接并重做所有相关unions。

这听起来有点像……


在开始实施任何东西之前,我想问一下是否有更智能的算法?

【问题讨论】:

  • 从你需要的3个操作中,不包括find,显而易见的实现是让union(x,y)xy之间创建一条边,然后findAll(x)做一个BFS。您确定不想在 SQL 中进行任何类型的递归吗?
  • @MattTimmermans 我正在使用没有 CONNECT BY 和 Hibernate 的 MySQL,所以我想,我真的不想递归。

标签: algorithm persistence union-find


【解决方案1】:

我建议您为集合创建一个哈希函数,并将其与数据库中的每个 x 一起存储在索引列中。在构造 union(x, y) 时,您可以计算新的哈希值并存储它。在findAll 上,使用此索引意味着您将只比较具有相同可能性的集合,这使得它相当快。并且查找没有什么花哨的,所以你可以在朴素的 SQL 中合理地实现它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    相关资源
    最近更新 更多