📄 ncbi_tree.hpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_tree.hpp,v $ * PRODUCTION Revision 1000.4 2004/06/01 19:07:49 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.33 * PRODUCTION * =========================================================================== */#ifndef CORELIB___NCBI_TREE__HPP#define CORELIB___NCBI_TREE__HPP/* $Id: ncbi_tree.hpp,v 1000.4 2004/06/01 19:07:49 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anatoliy Kuznetsov * * File Description: * Tree container. * */#include <corelib/ncbistd.hpp>#include <list>#include <stack>BEGIN_NCBI_SCOPE/** @addtogroup Tree * * @{ *//////////////////////////////////////////////////////////////////////////////////// Bi-directionaly linked N way tree.///template <class TValue> class CTreeNode{public: typedef TValue TValueType; typedef CTreeNode<TValue> TTreeType; typedef list<TTreeType*> TNodeList; typedef list<const TTreeType*> TConstNodeList; typedef typename TNodeList::iterator TNodeList_I; typedef typename TNodeList::const_iterator TNodeList_CI; /// Tree node construction /// /// @param /// value - node value CTreeNode(const TValue& value = TValue()); ~CTreeNode(); CTreeNode(const TTreeType& tree); CTreeNode& operator =(const TTreeType& tree); /// Get node's parent /// /// @return parent to the current node, NULL if it is a top /// of the tree const TTreeType* GetParent() const { return m_Parent; } /// Get node's parent /// /// @return parent to the current node, NULL if it is a top /// of the tree TTreeType* GetParent() { return m_Parent; } /// Get the topmost node /// /// @return global parent of the current node, this if it is a top /// of the tree const TTreeType* GetRoot() const; /// Get the topmost node /// /// @return global parent of the current node, this if it is a top /// of the tree TTreeType* GetRoot(); /// Return first const iterator on subnode list TNodeList_CI SubNodeBegin() const { return m_Nodes.begin(); } /// Return first iterator on subnode list TNodeList_I SubNodeBegin() { return m_Nodes.begin(); } /// Return last const iterator on subnode list TNodeList_CI SubNodeEnd() const { return m_Nodes.end(); } /// Return last iterator on subnode list TNodeList_I SubNodeEnd() { return m_Nodes.end(); } /// Return node's value const TValue& GetValue() const { return m_Value; } /// Return node's value TValue& GetValue() { return m_Value; } /// Set value for the node void SetValue(const TValue& value) { m_Value = value; } /// Remove subnode of the current node. Must be direct subnode. /// /// If subnode is not connected directly with the current node /// the call has no effect. /// /// @param /// subnode direct subnode pointer void RemoveNode(TTreeType* subnode); /// Remove subnode of the current node. Must be direct subnode. /// /// If subnode is not connected directly with the current node /// the call has no effect. /// /// @param /// it subnode iterator void RemoveNode(TNodeList_I it); enum EDeletePolicy { eDelete, eNoDelete }; /// Remove all immediate subnodes /// /// @param del /// Subnode delete policy void RemoveAllSubNodes(EDeletePolicy del = eDelete); /// Remove the subtree from the tree without freeing it /// /// If subnode is not connected directly with the current node /// the call has no effect. The caller is responsible for deletion /// of the returned subtree. /// /// @param /// subnode direct subnode pointer /// /// @return subtree pointer or NULL if requested subnode does not exist TTreeType* DetachNode(TTreeType* subnode); /// Remove the subtree from the tree without freeing it /// /// If subnode is not connected directly with the current node /// the call has no effect. The caller is responsible for deletion /// of the returned subtree. /// /// @param /// subnode direct subnode pointer /// /// @return subtree pointer or NULL if requested subnode does not exist TTreeType* DetachNode(TNodeList_I it); /// Add new subnode /// /// @param /// subnode subnode pointer void AddNode(TTreeType* subnode); /// Add new subnode whose value is (a copy of) val /// /// @param /// val value reference /// /// @return pointer to new subtree CTreeNode<TValue>* AddNode(const TValue& val = TValue()); /// Remove all subnodes from the source node and attach them to the /// current tree (node). Source node cannot be an ancestor of the /// current node void MoveSubnodes(TTreeType* src_tree_node); /// Insert new subnode before the specified location in the subnode list /// /// @param /// it subnote iterator idicates the location of the new subtree /// @param /// subnode subtree pointer void InsertNode(TNodeList_I it, TTreeType* subnode); /// Report whether this is a leaf node /// /// @return TRUE if this is a leaf node (has no children), /// false otherwise bool IsLeaf() const { return m_Nodes.empty(); }; /// Check if node is a direct or indirect parent of this node /// /// @param tree_node /// Node candidate /// @return TRUE if tree_node is a direct or indirect parent bool IsParent(const TTreeType& tree_node) const;protected: void CopyFrom(const TTreeType& tree); void SetParent(TTreeType* parent_node) { m_Parent = parent_node; } const TNodeList& GetSubNodes() const { return m_Nodes; }protected: TTreeType* m_Parent; ///< Pointer on the parent node TNodeList m_Nodes; ///< List of dependent nodes TValue m_Value; ///< Node value};template <class TId, class TValue>struct CTreePair{ TId id; TValue value; CTreePair() {} CTreePair(const TId& tid, const TValue& tvalue) : id(tid), value(tvalue) {} TId GetId() const { return id; }};/////////////////////////////////////////////////////////////////////////////////// Bi-directionaly linked N way tree./// Parameterized by id - value pairtemplate <class TId, class TValue> class CTreePairNode : public CTreeNode< CTreePair<TId, TValue> >{public: typedef TId TIdType; typedef TValue TValueType; typedef CTreeNode<CTreePair<TId, TValue> > TParent; typedef CTreePair<TId, TValue> TTreePair; typedef CTreePairNode<TId, TValue> TPairTreeType; typedef list<TPairTreeType*> TPairTreeNodeList; typedef list<const TPairTreeType*> TConstPairTreeNodeList;public: CTreePairNode(const TId& id = TId(), const TValue& value = TValue()); CTreePairNode(const CTreePairNode<TId, TValue>& tr); CTreePairNode<TId, TValue>& operator=(const CTreePairNode<TId, TValue>& tr); /// Add new subnode whose value is (a copy of) val /// /// @param /// val value reference /// /// @return pointer to new subtree CTreePairNode<TId, TValue>* AddNode(const TId& id, const TValue& value); /// Return node's value const TValueType& GetValue() const { return this->m_Value.value; } /// Return node's id const TIdType& GetId() const { return this->m_Value.id; } /// Return node's value TValueType& GetValue() { return this->m_Value.value; } /// Return node's id TIdType& GetId() { return this->m_Value.id; } /// Set value for the node void SetValue(const TValue& value) { this->m_Value.value = value; } /// Set id for the node void SetId(const TId& id) { this->m_Value.id = id; } /// Find tree nodes corresponding to the path from the top /// /// @param node_path /// hierachy of node ids to search for /// @param res /// list of discovered found nodes void FindNodes(const list<TId>& node_path, TPairTreeNodeList* res); /// Find tree nodes corresponding to the path from the top /// /// @param node_path /// hierachy of node ids to search for /// @param res /// list of discovered found nodes (const pointers) void FindNodes(const list<TId>& node_path, TConstPairTreeNodeList* res) const;};///////////////////////////////////////////////////////////////////////////////// Tree algorithms///// Tree traverse code returned by the traverse predicate functionenum ETreeTraverseCode{ eTreeTraverse, ///< Keep traversal eTreeTraverseStop, ///< Stop traversal (return form algorithm) eTreeTraverseStepOver ///< Do not traverse current node (pick the next one)};/// Depth-first tree traversal algorithm.////// Takes tree and visitor function and calls function for every /// node in the tree.////// Functor should have the next prototype:/// ETreeTraverseCode Func(TreeNode& node, int delta_level)/// where node is a reference to the visited node and delta_level /// reflects the current traverse direction(depth wise) in the tree, /// 0 - algorithm stays is on the same level/// 1 - we are going one level deep into the tree (from the root)/// -1 - we are traveling back by one level (getting close to the root)////// Algorithm calls the visitor function on the way back so it revisits/// some tree nodes. It is possible to implement both variants of tree /// traversal (pre-order and post-order)/// Visitor controls the traversal by returning ETreeTraverseCode////// @sa ETreeTraverseCode///template<class TTreeNode, class Fun>Fun TreeDepthFirstTraverse(TTreeNode& tree_node, Fun func){ int delta_level = 0; ETreeTraverseCode stop_scan; stop_scan = func(tree_node, delta_level); switch (stop_scan) { case eTreeTraverseStop: case eTreeTraverseStepOver: return func; case eTreeTraverse: break; } if (stop_scan) return func; delta_level = 1; TTreeNode* tr = &tree_node; typedef typename TTreeNode::TNodeList_I TTreeNodeIterator; TTreeNodeIterator it = tr->SubNodeBegin(); TTreeNodeIterator it_end = tr->SubNodeEnd(); if (it == it_end) return func; stack<TTreeNodeIterator> tree_stack; while (true) { tr = *it; stop_scan = eTreeTraverse; if (tr) { stop_scan = func(*tr, delta_level); switch (stop_scan) { case eTreeTraverseStop: return func; case eTreeTraverse: case eTreeTraverseStepOver: break; } } if ( (stop_scan != eTreeTraverseStepOver) && (delta_level >= 0) && (!tr->IsLeaf())) { // sub-node, going down tree_stack.push(it); it = tr->SubNodeBegin(); it_end = tr->SubNodeEnd(); delta_level = 1; continue; } ++it; if (it == it_end) { // end of level, going up if (tree_stack.empty()) { break; } it = tree_stack.top(); tree_stack.pop(); tr = *it; it_end = tr->GetParent()->SubNodeEnd(); delta_level = -1; continue; } // same level delta_level = 0; } // while func(tree_node, -1); return func;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -