“算法序列也可产生状态转移,但评价目标不同。在线算法在请求到达后立刻选择动作并与离线最优比较,动态数据结构则按 update/query 操作序列报告成本;追溯数据结构甚至允许编辑过去操作并重…”
时间线模型 ​
设 ADT 的更新按全序时间戳组成序列
部分追溯允许在任意过去修改更新,但只查询当前末端状态;完全追溯还允许 query
队列例子 ​
原时间线在
实现图像与证明责任 ​
通用朴素实现把时间线存成有序序列,每次追溯更新后重放后缀,更新可达
能力边界 ​
rollback 只按栈顺序撤销最近修改;partial/full persistence 决定从哪些版本查询和分叉;retroactivity 决定能否改写过去的操作。四者没有简单的同成本包含关系。完全追溯还可能比部分追溯严格更难;必须单独报告 query
可组合操作与难例 ​
若 ADT 状态是群元素,时间段摘要可取操作乘积,插入过去操作只需在平衡树叶修改并向根重算,得到
因此复杂度来自操作语义,而非时间线容器本身。历史树能在
时间编辑的执行轨迹 ​
考虑时间线 enqueue(a)@1, enqueue(b)@4, dequeue()@7。在时刻 3 插入 dequeue()@3 后,原来时刻 7 返回的元素会从 a 改为 b;这说明修改历史不能只修补时刻 3 的快照,而要重新建立其后的因果关系。
部分追溯结构只允许询问“现在”的状态:
- 按时间键把操作放入可分裂、可合并的搜索树;
- 每个子树保存该段操作对抽象状态的可组合摘要;
- 插入或删除历史操作后,只沿搜索路径重算摘要;
- 根摘要给出当前状态,却不一定支持任意过去时刻查询。
完全追溯还要在任意时间切开前缀并返回当时答案。若操作摘要不是结合的有限对象,例如队列中一次删除会改变后续大量返回值,就不能直接套用区间聚合;这正是“操作日志可排序”与“追溯接口可高效实现”之间的鸿沟。
参考资料
- Erik Demaine, John Iacono, Stefan Langerman, Retroactive Data Structures, ACM Transactions on Algorithms, 2007.
- James Driscoll et al., Making Data Structures Persistent, JCSS, 1989.