Как описано враздел,НавязчивыйКонтейнеры реализуются с использованием алгоритмов узлов, работающих на общих узлах.
Иногда использование интрузивных контейнеров дорого для некоторых сред, и программист может захотеть избежать всех шаблонных инстанциаций, связанных сBoost.контейнеры. Тем не менее, пользователь все еще может извлечь выгоду изBoost.используя алгоритмы узлов, потому что некоторые из этих алгоритмов, такие как алгоритмы красно-черного дерева, не тривиальны для записи.
Все классы алгоритмов узлов темплируются классом<NodeTraits>. Этот класс инкапсулирует необходимые внутренние объявления типов и операции, чтобы сделать узел совместимым с алгоритмами узлов. Каждый тип алгоритмов узлов имеет свои требования:
Пустой список формируется узлом, указатель которого на следующий узел указывает на себя.<circular_slist_algorithms>сконфигурирован с классом NodeTraits, который инкапсулирует информацию о узле, которым нужно манипулировать. NodeTraits должен поддерживать следующий интерфейс:
Типдефы:
<node>: Тип узла, который формирует круговой список
<node_ptr>: Тип указателя на узел (обычно узел*)
<const_node_ptr>: Тип указателя на узел const (обычно узел const*)
Статические функции:
<staticnode_ptrget_next(const_node_ptrn);>: Возвращает указатель на следующий узел, хранящийся в «n».
<staticvoidset_next(node_ptrn,node_ptrnext);>: Устанавливает указатель на следующий узел, хранящийся в "n" на "next".
Как только у нас есть конфигурация признаков узла, мы можем использоватьНавязчивыеалгоритмы с нашими узлами:
#include<boost/intrusive/circular_slist_algorithms.hpp>#include<cassert>structmy_node{my_node*next_;//other members...};//Define our own slist_node_traitsstructmy_slist_node_traits{typedefmy_nodenode;typedefmy_node*node_ptr;typedefconstmy_node*const_node_ptr;staticnode_ptrget_next(const_node_ptrn){returnn->next_;}staticvoidset_next(node_ptrn,node_ptrnext){n->next_=next;}};intmain(){typedefboost::intrusive::circular_slist_algorithms<my_slist_node_traits>algo;my_nodeone,two,three;//Create an empty singly linked list container://"one" will be the first node of the containeralgo::init_header(&one);assert(algo::count(&one)==1);//Now add a new nodealgo::link_after(&one,&two);assert(algo::count(&one)==2);//Now add a new node after "one"algo::link_after(&one,&three);assert(algo::count(&one)==3);//Now unlink the node after onealgo::unlink_after(&one);assert(algo::count(&one)==2);//Now unlink twoalgo::unlink(&two);assert(algo::count(&one)==1);return0;}
Пустой список формируется узлом, указатель которого на следующий узел указывает на себя.<circular_list_algorithms>сконфигурирован с классом NodeTraits, который инкапсулирует информацию о узле, которым нужно манипулировать. NodeTraits должен поддерживать следующий интерфейс:
Типдефы:
<node>: Тип узла, который формирует круговой список
<node_ptr>: Тип указателя на узел (обычно узел*)
<const_node_ptr>: Тип указателя на узел const (обычно узел const*)
Статические функции:
<staticnode_ptrget_next(const_node_ptrn);>: Возвращает указатель на следующий узел, хранящийся в «n».
<staticvoidset_next(node_ptrn,node_ptrnext);>: Устанавливает указатель на следующий узел, хранящийся в "n" на "next".
<staticnode_ptrget_previous(const_node_ptrn);>: Возвращает указатель на предыдущий узел, хранящийся в «n».
<staticvoidset_previous(node_ptrn,node_ptrprev);>: Устанавливает указатель на предыдущий узел, хранящийся в "n" на "prev".
Как только у нас есть конфигурация признаков узла, мы можем использоватьНавязчивыеалгоритмы с нашими узлами:
#include<boost/intrusive/circular_list_algorithms.hpp>#include<cassert>structmy_node{my_node*next_,*prev_;//other members...};//Define our own list_node_traitsstructmy_list_node_traits{typedefmy_nodenode;typedefmy_node*node_ptr;typedefconstmy_node*const_node_ptr;staticnode_ptrget_next(const_node_ptrn){returnn->next_;}staticvoidset_next(node_ptrn,node_ptrnext){n->next_=next;}staticnode*get_previous(const_node_ptrn){returnn->prev_;}staticvoidset_previous(node_ptrn,node_ptrprev){n->prev_=prev;}};intmain(){typedefboost::intrusive::circular_list_algorithms<my_list_node_traits>algo;my_nodeone,two,three;//Create an empty doubly linked list container://"one" will be the first node of the containeralgo::init_header(&one);assert(algo::count(&one)==1);//Now add a new node before "one"algo::link_before(&one,&two);assert(algo::count(&one)==2);//Now add a new node after "two"algo::link_after(&two,&three);assert(algo::count(&one)==3);//Now unlink the node after onealgo::unlink(&three);assert(algo::count(&one)==2);//Now unlink twoalgo::unlink(&two);assert(algo::count(&one)==1);//Now unlink onealgo::unlink(&one);assert(algo::count(&one)==1);return0;}
Эти алгоритмы являются статическими членами класса<rbtree_algorithms>:
template<classNodeTraits>structrbtree_algorithms;
Пустое дерево образуется узлом, указатель которого на родительский узел нулевой, указатели левого и правого узлов указывают на себя, и чей цвет красный.<rbtree_algorithms>сконфигурирован с классом NodeTraits, который инкапсулирует информацию о узле, которым нужно манипулировать. NodeTraits должен поддерживать следующий интерфейс:
Типдефы:
<node>: Тип узла, который образует круглое rbtree
<node_ptr>: Тип указателя на узел (обычно узел*)
<const_node_ptr>: Тип указателя на узел const (обычно узел const*)
<color>: Тип, который может хранить цвет узла
Статические функции:
<staticnode_ptrget_parent(const_node_ptrn);>: Возвращает указатель на родительский узел, хранящийся в «n».
<staticvoidset_parent(node_ptrn,node_ptrp);>: Устанавливает указатель на родительский узел, хранящийся в "n" на "p".
<staticnode_ptrget_left(const_node_ptrn);>: Возвращает указатель на левый узел, хранящийся в «n».
<staticvoidset_left(node_ptrn,node_ptrl);>: Устанавливает указатель на левый узел, хранящийся в "n" на "l".
<staticnode_ptrget_right(const_node_ptrn);>: Возвращает указатель на правый узел, хранящийся в «n».
<staticvoidset_right(node_ptrn,node_ptrr);>: Устанавливает указатель на правый узел, хранящийся в "n" на "r".
<staticcolorget_color(const_node_ptrn);>: Возвращает цвет, сохраненный в "n".
<staticvoidset_color(node_ptrn,colorc);>: Устанавливает цвет, сохраненный в "n" на "c".
<staticcolorred();>: Возвращает значение, представляющее красный цвет.
Как только у нас есть конфигурация признаков узла, мы можем использоватьНавязчивыеалгоритмы с нашими узлами:
#include<boost/intrusive/rbtree_algorithms.hpp>#include<cassert>structmy_node{my_node(inti=0):int_(i){}my_node*parent_,*left_,*right_;intcolor_;//other membersintint_;};//Define our own rbtree_node_traitsstructmy_rbtree_node_traits{typedefmy_nodenode;typedefmy_node*node_ptr;typedefconstmy_node*const_node_ptr;typedefintcolor;staticnode_ptrget_parent(const_node_ptrn){returnn->parent_;}staticvoidset_parent(node_ptrn,node_ptrparent){n->parent_=parent;}staticnode_ptrget_left(const_node_ptrn){returnn->left_;}staticvoidset_left(node_ptrn,node_ptrleft){n->left_=left;}staticnode_ptrget_right(const_node_ptrn){returnn->right_;}staticvoidset_right(node_ptrn,node_ptrright){n->right_=right;}staticcolorget_color(const_node_ptrn){returnn->color_;}staticvoidset_color(node_ptrn,colorc){n->color_=c;}staticcolorblack(){returncolor(0);}staticcolorred(){returncolor(1);}};structnode_ptr_compare{booloperator()(constmy_node*a,constmy_node*b){returna->int_<b->int_;}};intmain(){typedefboost::intrusive::rbtree_algorithms<my_rbtree_node_traits>algo;my_nodeheader,two(2),three(3);//Create an empty rbtree container://"header" will be the header node of the treealgo::init_header(&header);//Now insert node "two" in the tree using the sorting functoralgo::insert_equal_upper_bound(&header,&two,node_ptr_compare());//Now insert node "three" in the tree using the sorting functoralgo::insert_equal_lower_bound(&header,&three,node_ptr_compare());//Now take the first node (the left node of the header)my_node*n=header.left_;assert(n==&two);//Now go to the next noden=algo::next_node(n);assert(n==&three);//Erase a node just using a pointer to italgo::unlink(&two);//Erase a node using also the header (faster)algo::erase(&header,&three);return0;}
Пустое дерево образуется узлом, указатель которого на родительский узел нулевой, а указатели левого и правого узлов указывают на себя.<splaytree_algorithms>сконфигурирован с классом NodeTraits, который инкапсулирует информацию о узле, которым нужно манипулировать. NodeTraits должен поддерживать следующий интерфейс:
Типдефы:
<node>: Тип узла, который образует круговое сплиттри
<node_ptr>: Тип указателя на узел (обычно узел*)
<const_node_ptr>: Тип указателя на узел const (обычно узел const*)
Статические функции:
<staticnode_ptrget_parent(const_node_ptrn);>: Возвращает указатель на родительский узел, хранящийся в «n».
<staticvoidset_parent(node_ptrn,node_ptrp);>: Устанавливает указатель на родительский узел, хранящийся в "n" на "p".
<staticnode_ptrget_left(const_node_ptrn);>: Возвращает указатель на левый узел, хранящийся в «n».
<staticvoidset_left(node_ptrn,node_ptrl);>: Устанавливает указатель на левый узел, хранящийся в "n" на "l".
<staticnode_ptrget_right(const_node_ptrn);>: Возвращает указатель на правый узел, хранящийся в «n».
<staticvoidset_right(node_ptrn,node_ptrr);>: Устанавливает указатель на правый узел, хранящийся в "n" на "r".
Как только у нас есть конфигурация признаков узла, мы можем использоватьНавязчивыеалгоритмы с нашими узлами:
#include<boost/intrusive/splaytree_algorithms.hpp>#include<cassert>structmy_node{my_node(inti=0):int_(i){}my_node*parent_,*left_,*right_;//other membersintint_;};//Define our own splaytree_node_traitsstructmy_splaytree_node_traits{typedefmy_nodenode;typedefmy_node*node_ptr;typedefconstmy_node*const_node_ptr;staticnode_ptrget_parent(const_node_ptrn){returnn->parent_;}staticvoidset_parent(node_ptrn,node_ptrparent){n->parent_=parent;}staticnode_ptrget_left(const_node_ptrn){returnn->left_;}staticvoidset_left(node_ptrn,node_ptrleft){n->left_=left;}staticnode_ptrget_right(const_node_ptrn){returnn->right_;}staticvoidset_right(node_ptrn,node_ptrright){n->right_=right;}};structnode_ptr_compare{booloperator()(constmy_node*a,constmy_node*b){returna->int_<b->int_;}};intmain(){typedefboost::intrusive::splaytree_algorithms<my_splaytree_node_traits>algo;my_nodeheader,two(2),three(3);//Create an empty splaytree container://"header" will be the header node of the treealgo::init_header(&header);//Now insert node "two" in the tree using the sorting functoralgo::insert_equal_upper_bound(&header,&two,node_ptr_compare());//Now insert node "three" in the tree using the sorting functoralgo::insert_equal_lower_bound(&header,&three,node_ptr_compare());//Now take the first node (the left node of the header)my_node*n=header.left_;assert(n==&two);//Now go to the next noden=algo::next_node(n);assert(n==&three);//Erase a node just using a pointer to italgo::unlink(&two);//Erase a node using also the header (faster)algo::erase(&header,&three);return0;}
<avltree_algorithms>сконфигурирован с классом NodeTraits, который инкапсулирует информацию о узле, которым нужно манипулировать. NodeTraits должен поддерживать следующий интерфейс:
Типдефы:
<node>: Тип узла, который образует круговое avltree
<node_ptr>: Тип указателя на узел (обычно узел*)
<const_node_ptr>: Тип указателя на узел const (обычно узел const*)
<balance>Тип, который может представлять 3 типа баланса (обычно целое число)
Статические функции:
<staticnode_ptrget_parent(const_node_ptrn);>: Возвращает указатель на родительский узел, хранящийся в «n».
<staticvoidset_parent(node_ptrn,node_ptrp);>: Устанавливает указатель на родительский узел, хранящийся в "n" на "p".
<staticnode_ptrget_left(const_node_ptrn);>: Возвращает указатель на левый узел, хранящийся в «n».
<staticvoidset_left(node_ptrn,node_ptrl);>: Устанавливает указатель на левый узел, хранящийся в "n" на "l".
<staticnode_ptrget_right(const_node_ptrn);>: Возвращает указатель на правый узел, хранящийся в «n».
<staticvoidset_right(node_ptrn,node_ptrr);>: Устанавливает указатель на правый узел, хранящийся в "n" на "r".
<staticbalanceget_balance(const_node_ptrn);>: Возвращает балансовый фактор, хранящийся в «n».
<staticvoidset_balance(node_ptrn,balanceb);>: Устанавливает балансовый коэффициент, хранящийся в "n" на "b".
Как только у нас есть конфигурация признаков узла, мы можем использоватьНавязчивыеалгоритмы с нашими узлами:
#include<boost/intrusive/avltree_algorithms.hpp>#include<cassert>structmy_node{my_node(inti=0):int_(i){}my_node*parent_,*left_,*right_;intbalance_;//other membersintint_;};//Define our own avltree_node_traitsstructmy_avltree_node_traits{typedefmy_nodenode;typedefmy_node*node_ptr;typedefconstmy_node*const_node_ptr;typedefintbalance;staticnode_ptrget_parent(const_node_ptrn){returnn->parent_;}staticvoidset_parent(node_ptrn,node_ptrparent){n->parent_=parent;}staticnode_ptrget_left(const_node_ptrn){returnn->left_;}staticvoidset_left(node_ptrn,node_ptrleft){n->left_=left;}staticnode_ptrget_right(const_node_ptrn){returnn->right_;}staticvoidset_right(node_ptrn,node_ptrright){n->right_=right;}staticbalanceget_balance(const_node_ptrn){returnn->balance_;}staticvoidset_balance(node_ptrn,balanceb){n->balance_=b;}staticbalancenegative(){return-1;}staticbalancezero(){return0;}staticbalancepositive(){return1;}};structnode_ptr_compare{booloperator()(constmy_node*a,constmy_node*b){returna->int_<b->int_;}};intmain(){typedefboost::intrusive::avltree_algorithms<my_avltree_node_traits>algo;my_nodeheader,two(2),three(3);//Create an empty avltree container://"header" will be the header node of the treealgo::init_header(&header);//Now insert node "two" in the tree using the sorting functoralgo::insert_equal_upper_bound(&header,&two,node_ptr_compare());//Now insert node "three" in the tree using the sorting functoralgo::insert_equal_lower_bound(&header,&three,node_ptr_compare());//Now take the first node (the left node of the header)my_node*n=header.left_;assert(n==&two);//Now go to the next noden=algo::next_node(n);assert(n==&three);//Erase a node just using a pointer to italgo::unlink(&two);//Erase a node using also the header (faster)algo::erase(&header,&three);return0;}
<treap_algorithms>сконфигурирован с классом NodeTraits, который инкапсулирует информацию о узле, которым нужно манипулировать. NodeTraits должен поддерживать следующий интерфейс:
Типдефы:
<node>: Тип узла, который образует круговой потолок
<node_ptr>: Тип указателя на узел (обычно узел*)
<const_node_ptr>: Тип указателя на узел const (обычно узел const*)
Статические функции:
<staticnode_ptrget_parent(const_node_ptrn);>: Возвращает указатель на родительский узел, хранящийся в «n».
<staticvoidset_parent(node_ptrn,node_ptrp);>: Устанавливает указатель на родительский узел, хранящийся в "n" на "p".
<staticnode_ptrget_left(const_node_ptrn);>: Возвращает указатель на левый узел, хранящийся в «n».
<staticvoidset_left(node_ptrn,node_ptrl);>: Устанавливает указатель на левый узел, хранящийся в "n" на "l".
<staticnode_ptrget_right(const_node_ptrn);>: Возвращает указатель на правый узел, хранящийся в «n».
<staticvoidset_right(node_ptrn,node_ptrr);>: Устанавливает указатель на правый узел, хранящийся в "n" на "r".
Как только у нас есть конфигурация признаков узла, мы можем использоватьНавязчивыеалгоритмы с нашими узлами:
#include<boost/intrusive/treap_algorithms.hpp>#include<cassert>structmy_node{my_node(inti=0,unsignedintpriority=0):prio_(priority),int_(i){}my_node*parent_,*left_,*right_;intprio_;//other membersintint_;};//Define our own treap_node_traitsstructmy_treap_node_traits{typedefmy_nodenode;typedefmy_node*node_ptr;typedefconstmy_node*const_node_ptr;staticnode_ptrget_parent(const_node_ptrn){returnn->parent_;}staticvoidset_parent(node_ptrn,node_ptrparent){n->parent_=parent;}staticnode_ptrget_left(const_node_ptrn){returnn->left_;}staticvoidset_left(node_ptrn,node_ptrleft){n->left_=left;}staticnode_ptrget_right(const_node_ptrn){returnn->right_;}staticvoidset_right(node_ptrn,node_ptrright){n->right_=right;}};structnode_ptr_compare{booloperator()(constmy_node*a,constmy_node*b){returna->int_<b->int_;}};structnode_ptr_priority{booloperator()(constmy_node*a,constmy_node*b){returna->prio_<b->prio_;}};intmain(){typedefboost::intrusive::treap_algorithms<my_treap_node_traits>algo;my_nodeheader,two(2,5),three(3,1);//Create an empty treap container://"header" will be the header node of the treealgo::init_header(&header);//Now insert node "two" in the tree using the sorting functoralgo::insert_equal_upper_bound(&header,&two,node_ptr_compare(),node_ptr_priority());//Now insert node "three" in the tree using the sorting functoralgo::insert_equal_lower_bound(&header,&three,node_ptr_compare(),node_ptr_priority());//Now take the first node (the left node of the header)my_node*n=header.left_;assert(n==&two);//Now go to the next noden=algo::next_node(n);assert(n==&three);//Erase a node just using a pointer to italgo::unlink(&two,node_ptr_priority());//Erase a node using also the header (faster)algo::erase(&header,&three,node_ptr_priority());return0;}
Статья Node algorithms with custom NodeTraits раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 17. Boost.Intrusive может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.