【问题标题】:How does the Iterator in set works集合中的迭代器如何工作
【发布时间】:2011-10-07 00:38:44
【问题描述】:

我想知道在 c++ 的 STL 中设置的迭代器如何工作。我猜这个集合是使用二叉搜索树实现的,这意味着迭代器会按顺序遍历这棵树。但我的问题是,他们什么时候做这个遍历,一开始 当我们喜欢 它= s.begin() 并将遍历的指针存储在内部的某种堆栈中,并在迭代器中的每个增量上仅引用此数据结构 或者迭代器中的增量对树进行新的中序遍历。

我的意思是当我们像这样初始化时

     set<int>  s;
     set<int>::iterator it;

 //and then use it like:

      for(it = s.begin(); it!=s.end(); )
      {
           dosth();
           ++it;     // does this do a inorder traversal of the tree again to find the next 
                     // node or it gets the next node in the tree by reading the internal
                    // data structure(of inorder traversal) which is created when we do   s.begin().
      } 

【问题讨论】:

    标签: c++


    【解决方案1】:

    这是一个有趣的问题。正如 Nicol 指出的那样,它依赖于实现,在实现自己的集合时,您必须决定是偏爱更小的迭代器还是更快的遍历(您可以将更多数据放入迭代器以加快速度)。

    在我的平台(64 位)std::set&lt;T&gt;::iterator 的大小为 8 字节,这表明它只保留指向实际节点的指针。如果集合是使用某种树实现的,那么迭代器的递增绝对不是 O(1) 操作,需要遍历多达 log(N) 个附加节点(如果谈论平衡树)。我还检查了不同节点的++it 操作的速度,建议进行额外遍历的情况并不固定。对于通用集合容器来说完全没问题,因为它满足了树遍历复杂性的预期,并且人们通常认为迭代器尽可能小。如果你实现标准的递归树遍历它是完全一样的,你只是在堆栈上隐藏额外的节点访问。

    查看Implementing an iterator over a binary search tree 以获取有关实现您自己的树迭代器的更多详细信息。

    【讨论】:

    • 如果你在 64 位机器上工作,地址是 8 个字节。迭代器很可能被实现为一个唯一数据成员是指针的类——这正是 GNU 实现的工作原理。
    • 大卫,你完全正确,我忘记了我现在在 64 位机器上。谢谢,我已经编辑了我的帖子。
    【解决方案2】:

    它依赖于实现。但是,std::set 迭代器仅在迭代器引用从集合中移除的元素时才会失效。因此,您可以将std::set 迭代器视为树中的节点。 ++ 将其沿树的一个遍历方向移动,并且 -- 将其移动到另一个方向。

    请注意,迭代器由 begin 的其他函数返回,因此它们的有效性不仅限于开始/结束迭代。

    【讨论】:

    • 感谢您的回复....但是让我以其他方式提出我的问题..如果您被要求这样做,您将如何在 std::set 上实现迭代器的增量操作..假设在内部,节点是使用二叉搜索树而不是链表实现的...您是否会在每次增量操作时都对这棵树进行中序遍历做++它
    • @raja:你不能使用简单的链表来实现std::set。在集合中找到一个元素必须是 O(log N),但在链表中找到一个元素是 O(N)。它必然是一棵树。如果一个树节点保留了一个指向其父节点的指针,it++ 总是可以找到下一个最大值,而无需全树遍历。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 2021-12-14
    • 2012-07-07
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多