You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在boost::intrusive::rbtree中使用uint32_t作为节点指针?

自定义boost::intrusive::rbtree使用uint32_t作为节点索引

你代码里的核心错误在于把数组索引当成指针直接解引用,以及value traits里的语法错误,下面是修复后的完整方案:

错误点分析

  1. node_traits函数逻辑错误:get_parent等函数的参数是uint32_t(数组索引),但你直接用n->parent_,这是把索引当作指针操作,完全不符合语法。必须先通过索引找到数组中的节点对象,才能访问其成员。
  2. value_traits语法错误:构造函数初始化列表缺少冒号,且用_nodes.begin()(指针没有begin()方法),应该直接用指针相减计算索引。
  3. 未关联数组与node_traits:node_traits需要知道节点数组的地址,才能通过索引访问节点。

修复后的代码

节点定义

#include <boost/intrusive/rbtree.hpp>
#include <cstdint>

struct my_node
{
    my_node(int i = 0)
        : int_(i)
    {
    }
    uint8_t  color_;
    uint32_t parent_{0}, left_{0}, right_{0};
    int int_;
};

自定义node_traits

struct my_rbtree_node_traits
{
    typedef my_node        node;
    typedef uint32_t       node_ptr;
    typedef const uint32_t const_node_ptr;
    typedef uint8_t        color;

    // 静态指针指向节点数组,需全局初始化
    static my_node* s_nodes;

    static node_ptr get_parent(const_node_ptr n) { return s_nodes[n].parent_; }
    static void set_parent(node_ptr n, node_ptr parent) { s_nodes[n].parent_ = parent; }
    static node_ptr get_left(const_node_ptr n) { return s_nodes[n].left_; }
    static void set_left(node_ptr n, node_ptr left) { s_nodes[n].left_ = left; }
    static node_ptr get_right(const_node_ptr n) { return s_nodes[n].right_; }
    static void set_right(node_ptr n, node_ptr right) { s_nodes[n].right_ = right; }
    static color get_color(const_node_ptr n) { return s_nodes[n].color_; }
    static void set_color(node_ptr n, color c) { s_nodes[n].color_ = c; }
    static color black() { return color(0); }
    static color red() { return color(1); }
};

// 全局初始化静态数组指针
my_node* my_rbtree_node_traits::s_nodes = nullptr;

自定义stateful_value_traits

struct stateful_value_traits
{
    typedef my_rbtree_node_traits       node_traits;
    typedef node_traits::node           node;
    typedef node_traits::node_ptr       node_ptr;
    typedef node_traits::const_node_ptr const_node_ptr;
    typedef my_node                     value_type;
    typedef my_node*                    pointer;
    typedef const my_node*              const_pointer;

    pointer _nodes;

    // 构造函数:关联节点数组,并初始化node_traits的静态指针
    stateful_value_traits(pointer node_array)
        : _nodes(node_array)
    {
        node_traits::s_nodes = node_array;
    }

    // 将节点对象转换为数组索引
    node_ptr to_node_ptr(value_type &value) const
    {
        return static_cast<uint32_t>(&value - _nodes);
    }

    const_node_ptr to_node_ptr(const value_type &value) const
    {
        return static_cast<uint32_t>(&value - _nodes);
    }

    // 将数组索引转换为节点指针
    pointer to_value_ptr(node_ptr n) const
    {
        return &_nodes[n];
    }

    const_pointer to_value_ptr(const_node_ptr n) const
    {
        return &_nodes[n];
    }
};

使用示例

int main()
{
    const size_t NodeCount = 100;
    my_node node_array[NodeCount];

    // 创建value traits实例,关联节点数组
    stateful_value_traits vtraits(node_array);

    // 定义红黑树类型
    typedef boost::intrusive::rbtree<
        my_node,
        boost::intrusive::value_traits<stateful_value_traits>,
        boost::intrusive::node_traits<my_rbtree_node_traits>
    > MyRBTree;

    // 初始化红黑树
    MyRBTree tree(vtraits);

    // 插入节点
    for (size_t i = 0; i < NodeCount; ++i) {
        node_array[i].int_ = static_cast<int>(i);
        tree.insert_equal(node_array[i]);
    }

    // 遍历示例
    for (const auto& node : tree) {
        // 访问节点数据
        (void)node.int_;
    }

    return 0;
}

注意事项

  • 该方案适用于单节点数组场景,若需同时使用多个独立的红黑树(对应不同数组),静态指针会导致冲突,此时需改用包含数组指针和索引的结构体作为node_ptr(但会增加内存占用)。
  • 确保所有插入的节点都位于指定数组内,否则指针相减会得到无效索引。
  • 数组大小不能超过uint32_t的最大值(2^32-1),避免索引溢出。

内容的提问来源于stack exchange,提问作者摄魂怪

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 07:05:03