追溯数据结构是一种支持对数据结构进行有效修改的数据结构,在这种新的数据结构范式中,对数据结构执行的操作不仅是现在的,而且是过去的,这意味着操作可以改变甚至在消遣间隔中进行修改。
这些数据结构在处理需要定期更新的复杂应用程序时为我们提供了极大的灵活性,因为调整结构可以根据程序的工作模型进行调整,在现实世界中有各种情况需要从一系列操作中修改过去的操作。
需要追溯数据结构:
- 实现动态化:通常,一些静态算法需要动态数据结构来处理其输入,追溯数据结构可能是使这些算法动态化的最佳解决方案。
- 执行近似范围搜索:追溯数据结构有助于实现需要在任何时间点进行插入和删除等更新的操作,并在近似时间范围内返回输入。
- 避免额外的 O(log n) 开销:追溯数据结构帮助我们避免额外的 O(log n) 开销,并使应用程序能够执行诸如在段上构建高度段树、使用传统数据结构扩充根、扩充等操作具有 CDFC 结构的节点。
- 改变事务的历史顺序:追溯数据结构使应用程序能够有效地适应条件,例如撤销先前发生的错误,而无需重做此后的所有工作。
与持久化数据结构的比较:
尽管持久数据结构和追溯数据结构的概念在考虑时间维度时可能看起来相似,但它们处理时间元素的方式仍然使它们彼此不同。
- 持久化数据结构维护多个版本的数据结构,并且可以在一个版本的数据上实现操作以创建另一个版本。
- 在追溯数据结构的情况下,更改是直接对以前的版本进行的,并且不会创建其他修改过的以前的版本,这些版本在过去发生了数据更改。
追溯类型:
1. 部分追溯:任何数据结构都可以通过通用转换实现部分追溯。例如,下面插入一个具有初始状态 [1,2,3,4,5] 的部分追溯列表。然后我们可以添加或删除当前的操作。
以下是上述概念的Python伪代码:
# Python program to implement
# the above approach
x = PartiallyRetroactive([1, 2, 3, 4, 5])
def appendOne(lst):
return lst + [1]
# Three appendOnes by applying
# insertAgo()
x.insertAgo(appendOne, tminus = 0)
x.insertAgo(appendOne, tminus = 0)
x.insertAgo(appendOne, tminus = 0)
x.query()
# Three appendOnes by applying insertAgo()
[1, 2, 3, 4, 5, 1, 1, 1]
输出:
>>x.query() :
[1, 2, 3, 4, 5, 1, 1, 1]
我们还可以添加或删除过去的操作:
def MethodForAppendNum(lst):
return lst + [6]
## For Inserting into *two* operations ago
a.insertAgo(appendSix, tminus=2)
a.query()
[1, 2, 3, 4, 5, 1, 6, 1, 1]
## For Deleting the first appendOne
a.deleteAgo(tminus=3)
a.query()
[1, 2, 3, 4, 5, 6, 1, 1]
输出:
>>a.query() :
[1, 2, 3, 4, 5, 1, 6, 1, 1]
2. 一般全追溯:全追溯数据结构类似于它们的兄弟部分追溯数据结构,因为它们允许追溯插入和删除操作。然而,完全可追溯的数据结构也允许查询过去而不是现在。
以下是上述方法的Python伪代码:
b = MethodForFullyRetroactive([1,2,3])
b.insertAgo(appendOne, tminus = 0)
## This one should come last
b.insertAgo(appendSix, tminus = 0)
## This one should come first
b.insertAgo(appendTen, tminus =2)
b.query()
## The current state of the data structure
[1, 2, 3, 10, 1, 6]
b.query(1)
[1, 2, 3, 10, 1]
b.query(2)
[1, 2, 3, 10]
b.query(3)
## The state of the data structure way back
## in the past
[1, 2, 3]
输出:
>>b.query(1) :
[1, 2, 3, 10, 1, 6]
>>b.query(2) :
[1, 2, 3, 10]
>>b.query(3) :
[1, 2, 3]
应用:下面列出了追溯数据结构的一些应用
- 恢复:如果我们有一个硬件芯片损坏了,上面的数据丢失了,但现在已经修复了,我们可以从传感器读取数据,我们希望数据像硬件一样被插入到系统中从未损坏。
- 纠错:如果数据输入错误,必须纠正数据,消除错误输入的二次影响。
- 消遣中的数据操作:在消遣中修改数据有助于防止由于系统错误或手动错误而注入虚假数据的情况下的损坏控制。
- 坏数据:当处理在大型系统中输入数据时,特别是在天气网络中的传感器等系统中,需要大量自动数据传输、垃圾和不正确的数据可能会对应用程序造成巨大损害时,理想的解决方案是删除坏数据在过去的操作中,通过使用追溯数据结构来创建一个场景,就像从未发生过坏数据一样。
追溯数据结构的优点:
- 使我们可以灵活地纠正基于时间的更新,而无需在发生数据崩溃时使用经济高效的回滚操作。
- 这些数据结构可以最有效地应用于搜索问题,例如维护一些未知对象的集合 k,这些对象经过插入、删除和查询(x,s)等操作,因为在这里我们可以通过以下方式修改数据结构按时间顺序再次返回并检索我们想要的查询。
- 这些数据结构帮助我们解决分解的搜索问题,例如执行形式为 query(x, AuB) = f(query(x, A), query(x, B)) 的查询,其运行时间为 O(1)。
- 它们有助于有效地动态化静态算法。
追溯数据结构的缺点:
- 这些数据结构在更高的多项式时间内运行,需要大量的存储和计算资源。
- 这些数据结构在复杂的应用程序上运行良好,这些应用程序仅依靠基于时间的更新而没有适当的基于订单的目标,但不推荐用于生成基于严格规则的及时更新的简单且可扩展的应用程序,例如员工考勤管理系统、一次性密码生成器,因为实施这种数据结构可能会产生用于更改和修改信息的错误。
- 由于执行高多项式变换,因此涉及高维护成本。
- 如果使用追溯数据结构实现的应用程序没有包含有效的加密算法标准,那么由于没有时间记录可用,故意数据操纵甚至无法追踪的可能性很高。
自动追溯:我们自然会怀疑是否可以使用通用技术将数据结构自动转换为追溯形式,例如将指针机模型转换为有效的部分追溯数据结构?这种通用技术可以很好地补充现有的持久性数据结构,但是在追溯数据结构的情况下,追溯性与持久性根本不同,并且通常已知的技术不适用。
解决这个一般问题的一种简单方法是 回滚方法,其中辅助信息被存储,因为数据结构的所有更改都是由每个操作以这样的方式进行的,即每个更改都可以动态逆转,例如,为了启用内存写入操作的回滚,我们存储值那是以前在地址上的,因此它们的表现会根据追溯更改而有所不同。
追溯运行时间:取数据结构执行的一些操作来确定追溯数据结构的运行时间。例如,让 m 是对结构执行的操作数,让 r 是在追溯操作之前执行的操作数,n 是任何时候结构中存在的最大元素数。
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live