【问题标题】:What is the definition of _Rb_tree_increment in bits/stl_tree.h?bits/stl_tree.h中_Rb_tree_increment的定义是什么?
【发布时间】:2013-06-13 14:03:02
【问题描述】:

我想学习stl中的红黑树的代码。我在文件 bits/stl_tree.h 中找到了一个名为 _Rb_tree_increment 的函数

它写道:

 143   _GLIBCXX_PURE _Rb_tree_node_base*
 144   _Rb_tree_increment(_Rb_tree_node_base* __x) throw ();

但是我找不到这个函数的定义。有人可以帮忙吗?

非常感谢。

【问题讨论】:

    标签: c++ algorithm stl


    【解决方案1】:

    就像@Mike Seymour 说的,我在库的源路径上找到了定义,更准确地说是在gcc-4.8.1/libstdc++-v3/src/c++98/tree.cc

      static _Rb_tree_node_base*
      local_Rb_tree_increment(_Rb_tree_node_base* __x) throw ()
      {
        if (__x->_M_right != 0) 
          {
            __x = __x->_M_right;
            while (__x->_M_left != 0)
              __x = __x->_M_left;
          }
        else 
          {
            _Rb_tree_node_base* __y = __x->_M_parent;
            while (__x == __y->_M_right) 
              {
                __x = __y;
                __y = __y->_M_parent;
              }
            if (__x->_M_right != __y)
              __x = __y;
          }
        return __x;
      }
    
      _Rb_tree_node_base*
      _Rb_tree_increment(_Rb_tree_node_base* __x) throw ()
      {
        return local_Rb_tree_increment(__x);
      }
    
      const _Rb_tree_node_base*
      _Rb_tree_increment(const _Rb_tree_node_base* __x) throw ()
      {
        return local_Rb_tree_increment(const_cast<_Rb_tree_node_base*>(__x));
      }
    

    【讨论】:

    • @ragerdl 似乎 "increment" 是 c++ 对 "iterator::operator++" 的说法,这将在 en.wikipedia.org/wiki/Red%E2%80%93black_tree 上转换为 "sibling" @ 注意 "decrement" 是反向操作(指向我的前辈兄弟)未在指向的维基百科页面上定义。
    • 看看第二个if 声明:__x-&gt;_M_right 怎么可能等于__y(即它的祖父母)?
    • @user2023370 这种情况我也很复杂。我认为这是某种狡猾的漏洞。正如您在上面的 while 语句中看到的那样,x 可能会“争夺”到根,但 __y = __y-&gt;_M_parent。如果x 是根,你怎么能检查__x == __y-&gt;_M_right?这意味着根的父级不是nullptr?在我看来,根的父母是它的左孩子(也许,我不确定)
    • @user2023370 如果您查看相反函数的源代码_Rb_tree_decrement(),您实际上会在此处找到以下代码:if (... __x-&gt;_M_parent-&gt;_M_parent == __x)。所以是的,对于根,元素的祖父母可以是该元素本身。这可能是为了维护指向树的第一个和最后一个元素的特殊指针,这样begin()endstd::prev(end) 都是高效的,不需要筛选树来找到第一个或最后一个元素,分别。
    • @user2023370 通过查看_Rb_tree_insert_and_rebalance(),可以看出__header._M_parent实际上是指根节点,而__header._M_left__header._M_right指的是最左边的节点(=begin())和最右边的节点(=std::prev(end()))分别。 __header() 节点本身代表 end() 迭代器。您已经看到的特殊条件可能存在,因此 operator++operator-- 实际上不会超过开头/结尾。
    【解决方案2】:

    该定义取决于您拥有的标准库。不同的编译器供应商通过他们的编译器提供标准库的不同实现。看来您找到了一个非模板函数。这应该在某些 cpp 中定义,它将与编译器一起在 lib 文件中提供,因此您无法直接访问代码,因为它不会随您的编译器一起提供 - 这根本没有必要。

    如果您的编译器是专有编译器,例如来自 Microsoft 或 Borland,这就是你所能得到的。但是,如果您有 gcc,那么您很幸运:gcc 是开源的,您可以在线找到标准库的 gcc 实现的源代码。

    【讨论】:

    • OP 显然使用的是 GCC 附带的 stdlibc++ 实现。
    • 非常感谢,Arne,您的回答恰到好处(“您似乎找到了一个非模板函数。它应该在某些 cpp 中定义,它将与编译器一起在 lib 文件中提供”) . :)
    【解决方案3】:

    它将在库的源代码中,您可能没有。

    看起来您正在查看 GNU 库的标头,因此here 将是开始寻找源代码的好地方。

    【讨论】:

    • 谢谢,迈克。您的链接非常有用。 :)
    猜你喜欢
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 2022-10-15
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    相关资源
    最近更新 更多