如果我进行了从最小值到最大值的平衡BST的顺序遍历,我使用DFS来维护大小为lg(n)的堆栈。但如果我需要找到任意节点的inorder后继,那么它是最坏情况的lg(n)操作。但是如果我想按顺序迭代,id需要为每个节点重复找到inorder后继,产生O(n * lg(n))。 std :: set是否使用一些技巧进行顺序迭代,或者它真的花费了O(n * lg(n)),还是以某种方式摊销时间成本?
答案 0 :(得分:1)
有序迭代中没有技巧;您只需要一个O(1)机制来查找当前节点的父节点。
有序扫描遍历每个父子边缘两次:一次从父到子,一次从子到父。由于树中的非根节点的边数相同,因此完整的迭代执行Θ( n )转换以迭代 n 节点,是每个节点的摊销常数。
查找父级的常用方法是在节点中存储父链接。额外链接肯定会增加节点的大小(四个指针而不是三个指针),但成本是合理的。
如果不是C ++迭代器失效规则,它要求对有序关联容器元素的迭代器不能通过插入或删除其他元素而失效,那么就可以维护一个大小为O的堆栈(log <迭代器中的em> n )。这样的迭代器会很庞大但不是难以管理的(因为log n 在实践中限制为一个小的整数),但在任何树修改后它都不可用。