具有历史记录的搜索结构(持久性)
Posted
技术标签:
【中文标题】具有历史记录的搜索结构(持久性)【英文标题】:Search structure with history (persistence) 【发布时间】:2012-06-21 07:46:57 【问题描述】:我需要一个类似地图的数据结构(在 C++ 中)来存储具有以下功能的对 (Key,T):
您可以将新元素 (Key,T) 插入到当前结构中 可以根据当前结构中的Key搜索元素 您可以制作当前版本结构的“快照” 您可以切换到创建快照的结构版本之一,然后从那里继续所有操作 完全删除其中一个版本我不需要的东西
从结构中移除元素 将不同版本的结构合并为一个 迭代当前存储在结构中的所有(或部分)元素换句话说,您可以建立一些搜索结构,但在任何时候您都可以跳入历史,并以不同的方式扩展结构的早期/不同版本。稍后您可能会在这些不同的版本之间跳转。
在我的项目中,Key 和 T 可能是整数或指针值,而不是字符串。
主要目标是降低时间复杂度;空间消耗是次要的(但也应该是合理的)。澄清一下,对我来说 log(N)+log(S) (其中 N 个元素,S 个快照)就足够了,虽然更快更好:)
我对如何实现它有一些粗略的想法-例如:作为二叉搜索树的结构,插入新元素可以克隆从根到插入位置的路径,同时保留其余部分树完好无损。切换树版本相当于选择不同版本的根节点,其中一些更改根本不可见。
但是,要使此自定义树高效(例如自平衡),将需要一些额外的努力和仔细的编码。我当然可以自己做,但也许已经有现有的库可以做到这一点?
此外,这种数据结构可能有一个我根本不知道的专有名称,这使得我的 Google 搜索(或 SO 搜索)完全失败......
感谢您的帮助!
【问题讨论】:
你从来没有提到有序键;内部结构可以是一个哈希表,以便更快地访问。为每个快照提供一个指向其父快照的指针,并对快照计数的线性时间进行链式探测,但总项目计数的时间是恒定的。 为了帮助您的搜索:persistent 是用于限定此类数据结构的术语。它通常在底层使用引用计数来实现。 快照计数中的线性时间可能太慢。我更喜欢 log(N) 周围的东西,甚至完全隐藏快照 【参考方案1】:我认为您正在寻找的是不可变的地图。函数式(或受函数启发的)编程语言(例如 Haskell 或 Scala)具有您在 STL 中找到的大多数容器的不可变版本。诸如插入/删除等操作然后返回地图的副本(保留原件)以及包含您请求的修改的副本。在设计数据结构方面做了大量工作,以便副本能够尽可能多地指向原始数据结构,从而减少每个操作的时间和内存复杂性。
您可以在本书中找到更多详细信息,例如:http://www.amazon.co.uk/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504。
【讨论】:
这正是我想要回答的。我只是将 OCaml 添加到提供此类结构的语言列表中。 有提示很好,但 OP 要求提供支持此功能的库以避免重新实现它。老实说,我不知道这样的库是否存在,所以我想提示很好,但这不是核心问题。 感谢您的建议,我一定会看那本书,也许它可以让我更好地说明我的需求并帮助我的实施...... -IF- 我决定自己实施。跨度> @Alex:谢谢你,我找到了冈崎博士论文的pdf版本,同名:cs.cmu.edu/~rwh/theses/okasaki.pdf @CygnusX1:我很好地为您寻找现有的实现,但似乎没有出现。 FC++ 现在似乎已经退休了,并且从未有过树状结构 - 但没有其他任何事情被曝光。很高兴你找到了论文!【参考方案2】:在搜索一些持久性搜索树库时,我偶然发现了这个:
http://cg.scs.carleton.ca/~dana/pbst/
虽然它没有所需的完全相同的功能,但它似乎非常接近它。我会调查的。
(在此处发布,因为有人可能会发现它也很有用)
【讨论】:
以上是关于具有历史记录的搜索结构(持久性)的主要内容,如果未能解决你的问题,请参考以下文章