简体   繁体   English

二阶搜索树中的有序遍历复杂性(使用迭代器)?

[英]In-order traversal complexity in a binary search tree (using iterators)?

Related question: Time Complexity of InOrder Tree Traversal of Binary Tree O(N)? 相关问题: 二叉树O(N)的InOrder树遍历的时间复杂度? , however it is based on a traversal via recursion (so in O(log N) space) while iterators allow a consumption of only O(1) space. 但是它基于遍历递归(因此在O(log N)空间中),而迭代器只允许消耗O(1)空间。

In C++, there normally is a requirement that incrementing an iterator of a standard container be a O(1) operation. 在C ++中,通常需要将标准容器的迭代器递增为O(1)操作。 With most containers it's trivially proved, however with map and such, it seems a little more difficult. 对于大多数容器来说,它已被轻易证明,但是使用map等,似乎有点困难。

  • If a map were implemented as a skip-list, then the result would be obvious 如果将map实现为跳过列表,那么结果将是显而易见的
  • However they are often implemented as red-black trees (or at least as binary search trees) 然而,它们通常被实现为红黑树(或至少作为二叉搜索树)

So, during an in-order traversal there are moments where the "next" value is not so easily reached. 因此,在有序遍历期间,有时候“下一个”值不容易达到。 For example should you be pointing at the bottom-right leaf of the left subtree, then the next node to traverse is the root, which is depth steps away. 例如,如果您指向左子树的右下方叶子,则要遍历的下一个节点是根,这是depth步长。

I have tried "proving" that the algorithmic complexity (in terms of "steps") was amortized O(1), which seems alright. 我试过“证明”算法的复杂性(就“步骤”而言)是摊销的 O(1),这似乎没问题。 However I don't have the demonstration down yet. 但是我还没有进行演示。

Here is a small diagram I traced for a tree with a depth of 4, the numbers (in the place of the nodes) represent the number of steps to go from that node to the next one during an in-order traversal: 这是我为深度为4的树追踪的一个小图,数字(在节点的位置)表示在有序遍历期间从该节点到下一个节点的步数:

       3
   2       2
 1   1   1   1
1 2 1 3 1 2 1 4

Note: the right-most leaf has a cost of 4 in case this would be a sub-tree of a larger tree. 注意:如果这是一棵较大树的子树,则最右边的叶子的成本为4。

The sum is 28, for a total number of nodes of 15: thus a cost less than 2 per node, in average, which (if it holds up) would be a nice amortized cost. 总和为28,总节点数为15:因此平均每个节点的成本小于2,(如果它保持不变)将是一个很好的摊销成本。 So: 所以:

  • During in-order traversal, is incrementing the iterator really O(1) for a balanced (and full) binary search tree ? 在有序遍历期间,为平衡(和完整)二叉搜索树增加迭代器真的是O(1)吗?
  • May the result be extended to cover non-full binary search trees ? 可以将结果扩展到覆盖非完整二叉搜索树吗?

Yes, the amortized cost is indeed O(1) per iteration, for a any tree. 是的,对于任何树,摊销成本实际上是每次迭代的O(1)

The proof is based on the number of times you "visit" each node. 证明基于您“访问”每个节点的次数。
Leaves are visited only once. 叶子只访问过一次。 None leaves are visited at most 3 times: 没有叶子最多访问3次:

  1. when going from the parent to the node itself. 从父节点到节点本身。
  2. when coming back from the left subtree 当从左子树回来时
  3. when coming back from the right subtree 当从正确的子树回来时

There are no more visits to any nodes, thus if we sum the number of visits of each node, we get a number that is smaller then 3n , so the total number of visits of all nodes combined is O(n) , which gives us O(1) per step amortized. 没有更多的访问任何节点,因此如果我们总结每个节点的访问次数,我们得到一个小于3n ,所以所有节点的总访问次数是O(n) ,这给了我们每步O(1)摊销。

(Note since in a full tree there are n/2 leaves, we are getting the 2n you were encountering, I believe one can show that the sum of visits will be smaller then 2n for any tree, but this "optimization" is out of scope here IMO). (注意,因为在一个完整的树中有n / 2个叶子,我们得到你遇到的2n ,我相信可以证明任何树的访问总和将小于2n ,但是这个“优化”不在范围在这里IMO)。


The worst case per step is O(h) , which is O(logn) in a balanced tree, but might be O(n) in some cases. 每步的最坏情况是O(h) ,它是平衡树中的O(logn) ,但在某些情况下可能是O(n)


PS I have no idea how Red-Black trees are implemented in C++, but if your tree data structure contains a parent field from each node, it can replace the recursive stack and allow O(1) space consumption. PS我不知道如何在C ++中实现Red-Black树,但如果您的树数据结构包含来自每个节点的parent字段,它可以替换递归堆栈并允许O(1)空间消耗。 (This is of course "cheating" because storing n such fields is O(n) itself). (这当然是“作弊”,因为存储n这样的字段是O(n)本身)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM