如何在boost::intrusive::rbtree中使用uint32_t作为节点指针?
自定义boost::intrusive::rbtree使用uint32_t作为节点索引
你代码里的核心错误在于把数组索引当成指针直接解引用,以及value traits里的语法错误,下面是修复后的完整方案:
错误点分析
- node_traits函数逻辑错误:
get_parent等函数的参数是uint32_t(数组索引),但你直接用n->parent_,这是把索引当作指针操作,完全不符合语法。必须先通过索引找到数组中的节点对象,才能访问其成员。 - value_traits语法错误:构造函数初始化列表缺少冒号,且用
_nodes.begin()(指针没有begin()方法),应该直接用指针相减计算索引。 - 未关联数组与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,提问作者摄魂怪
相关产品推荐
相关产品推荐

