我在Haskell中寻找一个搜索树实现,它为共享结构的树提供了一个有效的差异函数。例如,如果我有一个大树x
(例如有数百万个元素)并且我在其中插入三个新元素以生成x'
,我希望能够调用difference x x'
返回这些元素,实现difference
,以便通过访问两棵树之间不共享的节点来找到感兴趣的元素。
我想到的场景就像版本控制系统一样,每个新版本都是从前一个版本派生出来的,我们可能需要找到任何两个版本之间的差异。
数据结构也应支持有效的插入,删除和查找操作(例如O(log n))。
这样的实现将依赖于System.Mem.StableName或Data.Unique.Id之类的东西来唯一地标记树中的每个节点,允许difference
函数有效地识别共享结构并避免降级到它。
这样的事情是否存在?如果没有,实施它的好策略是什么?我正在考虑修改像吴兴博的RBTree实现这样的东西,为每个节点添加唯一标签,但我对其他选项持开放态度。
答案 0 :(得分:1)
如果您想知道其中的一个大树x
,那么
您可以明确地跟踪更改,而不是计算差异:
-- extend a map with some insertions and deletions
data ExtMap k v = ExtMap { baseMap :: Map k v, changes :: Map k (Maybe v) }
fromMap :: Map k v -> ExtMap k v
fromMap x = ExtMap x Map.empty
toMap :: Ord k => ExtMap k v -> Map k v
toMap (ExtMap x y) = Map.mergeWithKey (\_ _ u -> u) id id x y
lookup :: Ord k => k -> ExtMap k v -> Maybe v
lookup k (ExtMap x y) = case Map.lookup k y of
Just mv -> mv -- if there is a change for this key, return that
Nothing -> Map.lookup k x -- otherwise look in the base map
insert :: Ord k => k -> v -> ExtMap k v -> ExtMap k v
insert k v (ExtMap x y) = ExtMap x (Map.insert k (Just v) y)
delete :: Ord k => k -> ExtMap k v -> ExtMap k v
delete k (ExtMap x y) = ExtMap x (Map.insert k Nothing y)
答案 1 :(得分:1)
我自己继续implemented this,修改了吴兴博的RBTree,以支持使用版本信息注释的值,然后可以使用diffVersion
来有效地计算差异。