tree_algorithms.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,626 行 · 第 1/4 页
HPP
1,626 行
NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced)); NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced)); //Now adjust adjacent nodes for newly inserted node if((temp = NodeTraits::get_left(new_node))){ NodeTraits::set_parent(temp, new_node); } if((temp = NodeTraits::get_right(new_node))){ NodeTraits::set_parent(temp, new_node); } if((temp = NodeTraits::get_parent(new_node)) && //The header has been already updated so avoid it temp != header){ if(NodeTraits::get_left(temp) == node_to_be_replaced){ NodeTraits::set_left(temp, new_node); } if(NodeTraits::get_right(temp) == node_to_be_replaced){ NodeTraits::set_right(temp, new_node); } } } //! <b>Requires</b>: p is a node from the tree except the header. //! //! <b>Effects</b>: Returns the next node of the tree. //! //! <b>Complexity</b>: Average constant time. //! //! <b>Throws</b>: Nothing. static node_ptr next_node(node_ptr p) { node_ptr p_right(NodeTraits::get_right(p)); if(p_right){ return minimum(p_right); } else { node_ptr x = NodeTraits::get_parent(p); while(p == NodeTraits::get_right(x)){ p = x; x = NodeTraits::get_parent(x); } return NodeTraits::get_right(p) != x ? x : uncast(p); } } //! <b>Requires</b>: p is a node from the tree except the leftmost node. //! //! <b>Effects</b>: Returns the previous node of the tree. //! //! <b>Complexity</b>: Average constant time. //! //! <b>Throws</b>: Nothing. static node_ptr prev_node(node_ptr p) { if(is_header(p)){ return maximum(NodeTraits::get_parent(p)); } else if(NodeTraits::get_left(p)){ return maximum(NodeTraits::get_left(p)); } else { node_ptr x = NodeTraits::get_parent(p); while(p == NodeTraits::get_left(x)){ p = x; x = NodeTraits::get_parent(x); } return x; } } //! <b>Requires</b>: p is a node of a tree but not the header. //! //! <b>Effects</b>: Returns the minimum node of the subtree starting at p. //! //! <b>Complexity</b>: Logarithmic to the size of the subtree. //! //! <b>Throws</b>: Nothing. static node_ptr minimum (node_ptr p) { for(node_ptr p_left = NodeTraits::get_left(p) ;p_left ;p_left = NodeTraits::get_left(p)){ p = p_left; } return p; } //! <b>Requires</b>: p is a node of a tree but not the header. //! //! <b>Effects</b>: Returns the maximum node of the subtree starting at p. //! //! <b>Complexity</b>: Logarithmic to the size of the subtree. //! //! <b>Throws</b>: Nothing. static node_ptr maximum(node_ptr p) { for(node_ptr p_right = NodeTraits::get_right(p) ;p_right ;p_right = NodeTraits::get_right(p)){ p = p_right; } return p; } //! <b>Requires</b>: node must not be part of any tree. //! //! <b>Effects</b>: After the function unique(node) == true. //! //! <b>Complexity</b>: Constant. //! //! <b>Throws</b>: Nothing. //! //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree. static void init(node_ptr node) { NodeTraits::set_parent(node, node_ptr(0)); NodeTraits::set_left(node, node_ptr(0)); NodeTraits::set_right(node, node_ptr(0)); }; //! <b>Effects</b>: Returns true if node is in the same state as if called init(node) //! //! <b>Complexity</b>: Constant. //! //! <b>Throws</b>: Nothing. static bool inited(const_node_ptr node) { return !NodeTraits::get_parent(node) && !NodeTraits::get_left(node) && !NodeTraits::get_right(node) ; }; //! <b>Requires</b>: node must not be part of any tree. //! //! <b>Effects</b>: Initializes the header to represent an empty tree. //! unique(header) == true. //! //! <b>Complexity</b>: Constant. //! //! <b>Throws</b>: Nothing. //! //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree. static void init_header(node_ptr header) { NodeTraits::set_parent(header, node_ptr(0)); NodeTraits::set_left(header, header); NodeTraits::set_right(header, header); } //! <b>Requires</b>: "disposer" must be an object function //! taking a node_ptr parameter and shouldn't throw. //! //! <b>Effects</b>: Empties the target tree calling //! <tt>void disposer::operator()(node_ptr)</tt> for every node of the tree //! except the header. //! //! <b>Complexity</b>: Linear to the number of element of the source tree plus the. //! number of elements of tree target tree when calling this function. //! //! <b>Throws</b>: If cloner functor throws. If this happens target nodes are disposed. template<class Disposer> static void clear_and_dispose(node_ptr header, Disposer disposer) { node_ptr source_root = NodeTraits::get_parent(header); if(!source_root) return; dispose_subtree(source_root, disposer); init_header(header); } //! <b>Requires</b>: header is the header of a tree. //! //! <b>Effects</b>: Unlinks the leftmost node from the tree, and //! updates the header link to the new leftmost node. //! //! <b>Complexity</b>: Average complexity is constant time. //! //! <b>Throws</b>: Nothing. //! //! <b>Notes</b>: This function breaks the tree and the tree can //! only be used for more unlink_leftmost_without_rebalance calls. //! This function is normally used to achieve a step by step //! controlled destruction of the tree. static node_ptr unlink_leftmost_without_rebalance(node_ptr header) { node_ptr leftmost = NodeTraits::get_left(header); if (leftmost == header) return node_ptr(0); node_ptr leftmost_parent(NodeTraits::get_parent(leftmost)); node_ptr leftmost_right (NodeTraits::get_right(leftmost)); bool is_root = leftmost_parent == header; if (leftmost_right){ NodeTraits::set_parent(leftmost_right, leftmost_parent); NodeTraits::set_left(header, tree_algorithms::minimum(leftmost_right)); if (is_root) NodeTraits::set_parent(header, leftmost_right); else NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right); } else if (is_root){ NodeTraits::set_parent(header, node_ptr(0)); NodeTraits::set_left(header, header); NodeTraits::set_right(header, header); } else{ NodeTraits::set_left(leftmost_parent, node_ptr(0)); NodeTraits::set_left(header, leftmost_parent); } return leftmost; } //! <b>Requires</b>: node is a node of the tree but it's not the header. //! //! <b>Effects</b>: Returns the number of nodes of the subtree. //! //! <b>Complexity</b>: Linear time. //! //! <b>Throws</b>: Nothing. static std::size_t count(const_node_ptr subtree) { if(!subtree) return 0; std::size_t count = 0; node_ptr p = minimum(uncast(subtree)); bool continue_looping = true; while(continue_looping){ ++count; node_ptr p_right(NodeTraits::get_right(p)); if(p_right){ p = minimum(p_right); } else { for(;;){ node_ptr q; if (p == subtree){ continue_looping = false; break; } q = p; p = NodeTraits::get_parent(p); if (NodeTraits::get_left(p) == q) break; } } } return count; } //! <b>Requires</b>: node is a node of the tree but it's not the header. //! //! <b>Effects</b>: Returns the number of nodes of the subtree. //! //! <b>Complexity</b>: Linear time. //! //! <b>Throws</b>: Nothing. static std::size_t size(const_node_ptr header) { node_ptr beg(begin_node(header)); node_ptr end(end_node(header)); std::size_t i = 0; for(;beg != end; beg = next_node(beg)) ++i; return i; } //! <b>Requires</b>: header1 and header2 must be the header nodes //! of two trees. //! //! <b>Effects</b>: Swaps two trees. After the function header1 will contain //! links to the second tree and header2 will have links to the first tree. //! //! <b>Complexity</b>: Constant. //! //! <b>Throws</b>: Nothing. static void swap_tree(node_ptr header1, node_ptr header2) { if(header1 == header2) return; node_ptr tmp; //Parent swap tmp = NodeTraits::get_parent(header1); NodeTraits::set_parent(header1, NodeTraits::get_parent(header2)); NodeTraits::set_parent(header2, tmp); //Left swap tmp = NodeTraits::get_left(header1); NodeTraits::set_left(header1, NodeTraits::get_left(header2)); NodeTraits::set_left(header2, tmp); //Right swap tmp = NodeTraits::get_right(header1); NodeTraits::set_right(header1, NodeTraits::get_right(header2)); NodeTraits::set_right(header2, tmp); //Now test parent node_ptr h1_parent(NodeTraits::get_parent(header1)); if(h1_parent){ NodeTraits::set_parent(h1_parent, header1); } else{ NodeTraits::set_left(header1, header1); NodeTraits::set_right(header1, header1); } node_ptr h2_parent(NodeTraits::get_parent(header2)); if(h2_parent){ NodeTraits::set_parent(h2_parent, header2); } else{ NodeTraits::set_left(header2, header2); NodeTraits::set_right(header2, header2); } } static bool is_header(const_node_ptr p) {/* node_ptr p_parent = NodeTraits::get_parent(p); if(!p_parent) return true; if(!NodeTraits::get_parent(p_parent) != p) return false; if(NodeTraits::get_left(p) != 0){ if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ is_header = true; } if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ is_header = true; } }*/ bool is_header = false; if(NodeTraits::get_parent(p) == p){ is_header = true; } else if(NodeTraits::get_parent(NodeTraits::get_parent(p)) == p){ if(NodeTraits::get_left(p) != 0){ if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ is_header = true; } if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ is_header = true; } } } return is_header; } //! <b>Requires</b>: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! //! <b>Effects</b>: Returns an node_ptr to the element that is equivalent to //! "key" according to "comp" or "header" if that element does not exist. //! //! <b>Complexity</b>: Logarithmic. //! //! <b>Throws</b>: If "comp" throws. template<class KeyType, class KeyNodePtrCompare> static node_ptr find (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) { node_ptr end = uncast(header); node_ptr y = lower_bound(header, key, comp); return (y == end || comp(key, y)) ? end : y; } //! <b>Requires</b>: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! //! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing //! all elements that are equivalent to "key" according to "comp" or an //! empty range that indicates the position where those elements would be //! if they there are no equivalent elements. //! //! <b>Complexity</b>: Logarithmic. //! //! <b>Throws</b>: If "comp" throws. template<class KeyType, class KeyNodePtrCompare> static std::pair<node_ptr, node_ptr> equal_range (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) { node_ptr y = uncast(header); node_ptr x = NodeTraits::get_parent(header); while(x){ if(comp(x, key)){ x = NodeTraits::get_right(x); } else if(comp(key, x)){ y = x; x = NodeTraits::get_left(x); } else{ node_ptr xu(x), yu(y); y = x, x = NodeTraits::get_left(x); xu = NodeTraits::get_right(xu); while(x){ if(comp(x, key)){ x = NodeTraits::get_right(x); } else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?