tree_algorithms.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,626 行 · 第 1/4 页
HPP
1,626 行
///////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2007.//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//// See http://www.boost.org/libs/intrusive for documentation.///////////////////////////////////////////////////////////////////////////////#ifndef BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP#define BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP#include <boost/intrusive/detail/config_begin.hpp>#include <boost/intrusive/detail/assert.hpp>#include <boost/intrusive/intrusive_fwd.hpp>#include <cstddef>#include <boost/intrusive/detail/utilities.hpp>namespace boost {namespace intrusive {namespace detail {//! This is an implementation of a binary search tree.//! A node in the search tree has references to its children and its parent. This //! is to allow traversal of the whole tree from a given node making the //! implementation of iterator a pointer to a node.//! At the top of the tree a node is used specially. This node's parent pointer //! is pointing to the root of the tree. Its left pointer points to the //! leftmost node in the tree and the right pointer to the rightmost one.//! This node is used to represent the end-iterator.//!//! +---------+ //! header------------------------------>| | //! | | //! +----------(left)--------| |--------(right)---------+ //! | +---------+ | //! | | | //! | | (parent) |//! | | |//! | | |//! | +---------+ |//! root of tree ..|......................> | | |//! | | D | |//! | | | |//! | +-------+---------+-------+ |//! | | | |//! | | | |//! | | | |//! | | | |//! | | | |//! | +---------+ +---------+ |//! | | | | | |//! | | B | | F | |//! | | | | | |//! | +--+---------+--+ +--+---------+--+ |//! | | | | | |//! | | | | | |//! | | | | | |//! | +---+-----+ +-----+---+ +---+-----+ +-----+---+ |//! +-->| | | | | | | |<--+ //! | A | | C | | E | | G | //! | | | | | | | | //! +---------+ +---------+ +---------+ +---------+ //!//! tree_algorithms is configured with a NodeTraits class, which encapsulates the//! information about the node to be manipulated. NodeTraits must support the//! following interface://!//! <b>Typedefs</b>://!//! <tt>node</tt>: The type of the node that forms the circular list//!//! <tt>node_ptr</tt>: A pointer to a node//!//! <tt>const_node_ptr</tt>: A pointer to a const node//!//! <b>Static functions</b>://!//! <tt>static node_ptr get_parent(const_node_ptr n);</tt>//! //! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>//!//! <tt>static node_ptr get_left(const_node_ptr n);</tt>//! //! <tt>static void set_left(node_ptr n, node_ptr left);</tt>//!//! <tt>static node_ptr get_right(const_node_ptr n);</tt>//! //! <tt>static void set_right(node_ptr n, node_ptr right);</tt>template<class NodeTraits>class tree_algorithms{ public: typedef typename NodeTraits::node node; typedef NodeTraits node_traits; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; //! This type is the information that will be filled by insert_unique_check struct insert_commit_data { insert_commit_data() : link_left(false) , node(0) {} bool link_left; node_ptr node; }; struct nop_erase_fixup { void operator()(node_ptr, node_ptr){} }; /// @cond private: template<class Disposer> struct dispose_subtree_disposer { dispose_subtree_disposer(Disposer &disp, node_ptr subtree) : disposer_(&disp), subtree_(subtree) {} void release() { disposer_ = 0; } ~dispose_subtree_disposer() { if(disposer_){ dispose_subtree(subtree_, *disposer_); } } Disposer *disposer_; node_ptr subtree_; }; static node_ptr uncast(const_node_ptr ptr) { return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr))); } /// @endcond public: static node_ptr begin_node(const_node_ptr header) { return node_traits::get_left(header); } static node_ptr end_node(const_node_ptr header) { return uncast(header); } //! <b>Requires</b>: node is a node of the tree or an node initialized //! by init(...) or init_node. //! //! <b>Effects</b>: Returns true if the node is initialized by init() or init_node(). //! //! <b>Complexity</b>: Constant time. //! //! <b>Throws</b>: Nothing. static bool unique(const_node_ptr node) { return NodeTraits::get_parent(node) == 0; } static node_ptr get_header(const_node_ptr node) { node_ptr h = uncast(node); if(NodeTraits::get_parent(node)){ h = NodeTraits::get_parent(node); while(!is_header(h)) h = NodeTraits::get_parent(h); } return h; } //! <b>Requires</b>: node1 and node2 can't be header nodes //! of two trees. //! //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted //! in the position node2 before the function. node2 will be inserted in the //! position node1 had before the function. //! //! <b>Complexity</b>: Logarithmic. //! //! <b>Throws</b>: Nothing. //! //! <b>Note</b>: This function will break container ordering invariants if //! node1 and node2 are not equivalent according to the ordering rules. //! //!Experimental function static void swap_nodes(node_ptr node1, node_ptr node2) { if(node1 == node2) return; node_ptr header1(get_header(node1)), header2(get_header(node2)); swap_nodes(node1, header1, node2, header2); } //! <b>Requires</b>: node1 and node2 can't be header nodes //! of two trees with header header1 and header2. //! //! <b>Effects</b>: Swaps two nodes. After the function node1 will be inserted //! in the position node2 before the function. node2 will be inserted in the //! position node1 had before the function. //! //! <b>Complexity</b>: Constant. //! //! <b>Throws</b>: Nothing. //! //! <b>Note</b>: This function will break container ordering invariants if //! node1 and node2 are not equivalent according to the ordering rules. //! //!Experimental function static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) { if(node1 == node2) return; //node1 and node2 must not be header nodes //BOOST_INTRUSIVE_INVARIANT_ASSERT((header1 != node1 && header2 != node2)); if(header1 != header2){ //Update header1 if necessary if(node1 == NodeTraits::get_left(header1)){ NodeTraits::set_left(header1, node2); } if(node1 == NodeTraits::get_right(header1)){ NodeTraits::set_right(header1, node2); } if(node1 == NodeTraits::get_parent(header1)){ NodeTraits::set_parent(header1, node2); } //Update header2 if necessary if(node2 == NodeTraits::get_left(header2)){ NodeTraits::set_left(header2, node1); } if(node2 == NodeTraits::get_right(header2)){ NodeTraits::set_right(header2, node1); } if(node2 == NodeTraits::get_parent(header2)){ NodeTraits::set_parent(header2, node1); } } else{ //If both nodes are from the same tree //Update header if necessary if(node1 == NodeTraits::get_left(header1)){ NodeTraits::set_left(header1, node2); } else if(node2 == NodeTraits::get_left(header2)){ NodeTraits::set_left(header2, node1); } if(node1 == NodeTraits::get_right(header1)){ NodeTraits::set_right(header1, node2); } else if(node2 == NodeTraits::get_right(header2)){ NodeTraits::set_right(header2, node1); } if(node1 == NodeTraits::get_parent(header1)){ NodeTraits::set_parent(header1, node2); } else if(node2 == NodeTraits::get_parent(header2)){ NodeTraits::set_parent(header2, node1); } //Adjust data in nodes to be swapped //so that final link swap works as expected if(node1 == NodeTraits::get_parent(node2)){ NodeTraits::set_parent(node2, node2); if(node2 == NodeTraits::get_right(node1)){ NodeTraits::set_right(node1, node1); } else{ NodeTraits::set_left(node1, node1); } } else if(node2 == NodeTraits::get_parent(node1)){ NodeTraits::set_parent(node1, node1); if(node1 == NodeTraits::get_right(node2)){ NodeTraits::set_right(node2, node2); } else{ NodeTraits::set_left(node2, node2); } } } //Now swap all the links node_ptr temp; //swap left link temp = NodeTraits::get_left(node1); NodeTraits::set_left(node1, NodeTraits::get_left(node2)); NodeTraits::set_left(node2, temp); //swap right link temp = NodeTraits::get_right(node1); NodeTraits::set_right(node1, NodeTraits::get_right(node2)); NodeTraits::set_right(node2, temp); //swap parent link temp = NodeTraits::get_parent(node1); NodeTraits::set_parent(node1, NodeTraits::get_parent(node2)); NodeTraits::set_parent(node2, temp); //Now adjust adjacent nodes for newly inserted node 1 if((temp = NodeTraits::get_left(node1))){ NodeTraits::set_parent(temp, node1); } if((temp = NodeTraits::get_right(node1))){ NodeTraits::set_parent(temp, node1); } if((temp = NodeTraits::get_parent(node1)) && //The header has been already updated so avoid it temp != header2){ if(NodeTraits::get_left(temp) == node2){ NodeTraits::set_left(temp, node1); } if(NodeTraits::get_right(temp) == node2){ NodeTraits::set_right(temp, node1); } } //Now adjust adjacent nodes for newly inserted node 2 if((temp = NodeTraits::get_left(node2))){ NodeTraits::set_parent(temp, node2); } if((temp = NodeTraits::get_right(node2))){ NodeTraits::set_parent(temp, node2); } if((temp = NodeTraits::get_parent(node2)) && //The header has been already updated so avoid it temp != header1){ if(NodeTraits::get_left(temp) == node1){ NodeTraits::set_left(temp, node2); } if(NodeTraits::get_right(temp) == node1){ NodeTraits::set_right(temp, node2); } } } //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree //! and new_node must not be inserted in a tree. //! //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the //! tree with new_node. The tree does not need to be rebalanced //! //! <b>Complexity</b>: Logarithmic. //! //! <b>Throws</b>: Nothing. //! //! <b>Note</b>: This function will break container ordering invariants if //! new_node is not equivalent to node_to_be_replaced according to the //! ordering rules. This function is faster than erasing and inserting //! the node, since no rebalancing and comparison is needed. //! //!Experimental function static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) { if(node_to_be_replaced == new_node) return; replace_node(node_to_be_replaced, get_header(node_to_be_replaced), new_node); } //! <b>Requires</b>: node_to_be_replaced must be inserted in a tree //! with header "header" and new_node must not be inserted in a tree. //! //! <b>Effects</b>: Replaces node_to_be_replaced in its position in the //! tree with new_node. The tree does not need to be rebalanced //! //! <b>Complexity</b>: Constant. //! //! <b>Throws</b>: Nothing. //! //! <b>Note</b>: This function will break container ordering invariants if //! new_node is not equivalent to node_to_be_replaced according to the //! ordering rules. This function is faster than erasing and inserting //! the node, since no rebalancing or comparison is needed. //! //!Experimental function static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) { if(node_to_be_replaced == new_node) return; //Update header if necessary if(node_to_be_replaced == NodeTraits::get_left(header)){ NodeTraits::set_left(header, new_node); } if(node_to_be_replaced == NodeTraits::get_right(header)){ NodeTraits::set_right(header, new_node); } if(node_to_be_replaced == NodeTraits::get_parent(header)){ NodeTraits::set_parent(header, new_node); } //Now set data from the original node node_ptr temp; NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?