一尘不染

在二叉搜索树上实现迭代器

algorithm

我最近一直在编码一堆不同的二进制搜索树实现(AVL,splay,treap),并且很好奇是否有一种特别好的方法来编写迭代器以遍历这些结构。我现在使用的解决方案是让BST中的每个节点存储指向树中下一个和上一个元素的指针,这将迭代减少为标准的链表迭代。但是,我对这个答案并不满意。它通过两个指针(下一个和上一个)增加了每个节点的空间使用率,从某种意义上说,这只是作弊。

我知道一种构建二叉搜索树迭代器的方法,该迭代器使用O(h)辅助存储空间(其中h是树的高度),方法是使用堆栈来跟踪边界节点以供以后探索,但是我由于内存占用,我拒绝对此进行编码。我希望有某种方法可以构建仅使用恒定空间的迭代器。

我的问题是-有没有一种方法可以在具有以下属性的二进制搜索树上设计迭代器?

  1. 元素以升序访问(即有序遍历)
  2. next()hasNext()查询在O(1)时间运行。
  3. 内存使用量为O(1)

为了简化起见,如果您假设树结构在迭代过程中没有改变形状(即没有插入,删除或旋转),那就很好了,但是如果有确实可以解决这个问题的解决方案,那真的很酷。


阅读 220

收藏
2020-07-28

共1个答案

一尘不染

可能最简单的迭代器存储最后看到的密钥,然后在下一次迭代时,在树中搜索该密钥的最小上限。迭代为O(log
n)。这具有非常简单的优点。如果密钥较小,则迭代器也较小。当然,它的缺点是迭代树的方法相对较慢。它也不适用于非唯一序列。

有些树正好使用您已经使用的实现,因为对于它们的特定用途来说,扫描非常快很重要。如果每个节点中的键数很大,那么存储同级指针的代价就不会太麻烦。大多数B树使用此方法。

许多搜索树实现都在每个节点上保留一个父指针,以简化其他操作。如果有,则可以使用指向最后看到的节点的简单指针作为迭代器的状态。在每次迭代中,您都在最后看到的节点的父节点中寻找下一个子节点。如果没有更多的兄弟姐妹,那么您将再上一层。

如果这些技术都不适合您,则可以使用存储在迭代器中的一堆节点。当正常遍历搜索树时,此功能与函数调用堆栈的功能相同,但是您无需将同级循环并在子级上进行递归,而是将子级推入堆栈并返回每个后续的同级。

2020-07-28