对于自动机算法,我需要一种功能语言的快速Union-Find数据结构。由于我需要正式证明数据结构的正确性,我宁愿选择一个简单的结构。
我要做的是计算集合S
w.r.t中元素的等价类。关系R ⊆ S × S
。我最终希望得到的是一些函数f: S → S
,它将S
的任何元素映射到其R
- 等价类的(规范)代表。通过“规范”,我的意思是我不关心它是什么代表,只要它对于一个等价类的所有元素都是相同的,即我希望f x = f y ⟺ (x,y) ∈ R
持有。
在函数式语言中,最佳数据结构和算法是什么?我应该补充一点,我真的需要“正常”的功能代码,即没有可变性/状态变换器monad。
编辑:与此同时,我提出了这个算法:
m := empty map
for each s ∈ S do
if m s = None then
for each t in {t | (s,t) ∈ R}
m := m[t ↦ s]
这将创建一个映射,将S
的任何元素映射到其等价类的代表,其中代表是迭代超过S
的第一个元素。我认为这实际上有线性时间(如果地图操作是不变的)。但是,我仍然对其他解决方案感兴趣,因为我不知道这在实践中效率如何。
(我的关系在内部表示为“S→(S Set)选项”,因此迭代超过{t |(s,t)∈R} - 这是对该结构的廉价操作。)
答案 0 :(得分:7)
AFAIK(并且快速搜索没有消除我),没有已知的具有可比较的渐近性能(摊销的逆阿克曼函数)的传统disjoint-set datastructure的纯功能等价物。 (传统的数据结构不是纯粹的功能,因为它需要破坏性的更新来执行路径压缩)
如果你没有对功能纯度设定死角,你可以使用破坏性更新,并实现传统的数据结构。
如果您不关心匹配渐近性能,可以用persistent associative map替换传统数据结构的随机访问数组,代价是额外的O(log N)性能因子,以及需要验证其正确性。
如果您希望最大限度地简化验证目的,并且在上述任何一个方面都没有设置,则可以使用可更新数组和删除逐个级别的优化。 IIRC会产生O(log N)摊销的最坏情况,但实际上可能会提高实际执行速度(因为不再需要存储或管理等级)。