tree_algo.hpp
来自「ncbi源码」· HPP 代码 · 共 898 行 · 第 1/2 页
HPP
898 行
/// Create set of all sub-nodes (recursively)/// /// @param tree_node/// root node/// @param back_ins/// Back insert iterator (represents set)///template<class TNode, class TBackInsert>void TreeMakeSet(const TNode& tree_node, TBackInsert back_ins){ TNode* node = const_cast<TNode*>(&tree_node); CTreeIdToSetFunc<TNode, TBackInsert> func(back_ins); TreeDepthFirstTraverse(*node, func);}/// Create set of all immediate sub-nodes (one level down from the root)/// /// @param tree_node/// root node/// @param back_ins/// Back insert iterator (represents set)///template<class TNode, class TBackInsert>void TreeMakeSubNodesSet(const TNode& tree_node, TBackInsert back_ins){ typename TNode::TNodeList_CI it = tree_node.SubNodeBegin(); typename TNode::TNodeList_CI it_end = tree_node.SubNodeEnd(); for(;it != it_end; ++it) { const TNode* node = *it; *back_ins = node->GetValue().GetId(); ++back_ins; }}/// Functor to convert tree to a nodelist by the set pattern////// @internaltemplate<class TTreeNode, class TSet, class TNodeList>class CTreeSet2NodeListFunc{public: CTreeSet2NodeListFunc(const TSet& node_set, TNodeList* node_list) : m_NodeSet(node_set), m_NodeList(node_list) {} ETreeTraverseCode operator()(const TTreeNode& node, int delta_level=0) { if (delta_level >= 0) { unsigned id = node.GetValue().GetId(); bool b = m_NodeSet[id]; if (b) { m_NodeList->push_back(&node); } } return eTreeTraverse; }private: const TSet& m_NodeSet; TNodeList* m_NodeList;};/// Convert set of node ids to list of nodes////// Traverses the tree, if node is in the set adds node pointer to /// the nodelist.///template<class TNode, class TSet, class TNodeList>void TreeSetToNodeList(const TNode& tree_node, const TSet& node_set, TNodeList& nlist){ TNode* node = const_cast<TNode*>(&tree_node); CTreeSet2NodeListFunc<TNode, TSet, TNodeList> func(node_set, &nlist); TreeDepthFirstTraverse(node, func);}/// Class-algorithm to compute Non Redundant Set////// Takes a single nodelist as an arguiment and copies every node/// which has no ancestors in the source set. /// @note Result set might be not minimal///template<class TNode, class TSet, class TNodeList>class CTreeNonRedundantSet{public: void operator()(const TNodeList& src_nlist, TNodeList& dst_nlist) { TSet src_set; TreeListToSet(src_nlist, src_set.inserter()); TSet ancestor_set; ITERATE(typename TNodeList, it, src_nlist) { TNode* snode = *it; ancestor_set.clear(); TreeMakeParentsSet(*snode, ancestor_set.inserter()); ancestor_set &= src_set; unsigned cnt = ancestor_set.count(); if (cnt == 0) { // source set contains no ancestors of the node // node is part of the non redundant set dst_nlist.push_back(snode); } } // ITERATE }};/// Functor takes a single nodelist as an argument and tries to/// push that nodelist as high as it can. If all of the childred /// of a given node are in the nodelist, the children are removed from /// the nodelist and the parent is added. The process is repeated util/// it cannot be reduced anymore.///template<class TNode, class TSet, class TNodeList>class CTreeMinimalSet{public: /// Compute minimal set. /// /// @param src_nlist /// Source node list /// @param dst_nlist /// Destination node list /// @param ignore_set /// Set of node ids to ignore when we do reduction /// void operator()(const TNodeList& src_nlist, TNodeList& dst_nlist, const TSet* ignore_set = 0) { MinimalSet(src_nlist, dst_nlist, ignore_set); }protected: // The main workhorse function void MinimalSet(const TNodeList& src_nlist, TNodeList& dst_nlist, const TSet* ignore_set = 0) { TSet src_set; TreeListToSet(src_nlist, src_set.inserter()); TSet child_set; TSet tmp_set; bool moved_up; // flag that group of nodes got substituted for parent do { moved_up = CheckNodeList(src_nlist, dst_nlist, src_set, tmp_set, child_set, ignore_set); if (moved_up) { moved_up = CheckNodeList(dst_nlist, dst_nlist, src_set, tmp_set, child_set, ignore_set); } } while (moved_up); // repeat while we can move nodes up loop_restart: // clean the destination node list from reduced parents NON_CONST_ITERATE(typename TNodeList, it, dst_nlist) { TNode* snode = *it; unsigned id = snode->GetValue().GetId(); // check if node was excluded from the source set bool b = src_set[id]; if (!b) { dst_nlist.erase(it); goto loop_restart; } } // add non reduced source nodes to the destination list ITERATE(typename TNodeList, it, src_nlist) { TNode* snode = *it; unsigned id = snode->GetValue().GetId(); bool b = src_set[id]; if (b) { dst_nlist.push_back(snode); } } } bool CheckNodeList(const TNodeList& nlist, TNodeList& dst_nlist, TSet& src_set, TSet& tmp_set, TSet& child_set, const TSet* ignore_set) { TNodeList tmp_nlist; // (to avoid problems when &nlist == &dst_nlist) bool promo_flag = false; ITERATE(typename TNodeList, it, nlist) { TNode* snode = *it; unsigned id = snode->GetValue().GetId(); TNode* parent = snode->GetParent(); // check if node was excluded from the source set bool b = src_set[id]; if (!b || (parent == 0)) continue; unsigned parent_id = parent->GetValue().GetId(); child_set.clear(); // Add immediate subnodes TreeMakeSubNodesSet(*parent, child_set.inserter()); tmp_set = child_set; tmp_set -= src_set; if (ignore_set) { tmp_set -= *ignore_set; } if (tmp_set.none()) { // we can move up to the parent // Add ALL subordinate node, not just children TreeMakeSet(*parent, child_set.inserter()); src_set -= child_set; bool parent_in = src_set[parent_id]; if (!parent_in) { src_set[parent_id] = true; // // precautionary measure: make sure we do not // invalidate the source iterator // (TNodeList can be a vector) // if (&nlist != &dst_nlist) { dst_nlist.push_back(parent); } else { tmp_nlist.push_back(parent); } } promo_flag = true; } } // ITERATE // copy temp node list to the dst set // ITERATE(typename TNodeList, it, tmp_nlist) { TNode* snode = *it; dst_nlist.push_back(snode); } return promo_flag; }};/// Utility to join to node lists according to a set of idstemplate<class TNode, class TSet, class TNodeList>class CNodesToBitset{public: /// Join two node lists /// /// @param src_nlist_a /// node list 1 /// @param src_nlist_b /// node list 2 /// @param mask_set /// subset of two nodelists assigns nodes coming to dst_list /// @param dst_list /// destination node list /// @param dst_set /// auxiliary set used to track in target set /// (to make sure we will have non repeated list of nodes) void JoinNodeList(const TNodeList& src_nlist_a, const TNodeList& src_nlist_b, const TSet& mask_set, TNodeList& dst_list, TSet& dst_set) { dst_set.clear(); MaskCopyNodes(src_nlist_a, mask_set, dst_list, dst_set); unsigned dst_count = dst_set.count(); unsigned src_count = mask_set.count(); if (src_count != dst_count) { MaskCopyNodes(src_nlist_b, mask_set, dst_list, dst_set); } } /// Copy nodes from the source node list to destination /// if nodes are in the mask set and not yet in the destination set void MaskCopyNodes(const TNodeList& src_nlist, const TSet& mask_set, TNodeList& dst_list, TSet& dst_set) { ITERATE(typename TNodeList, it, src_nlist) { unsigned id = (*it)->GetValue().GetId(); bool exists = mask_set[id]; if (exists) { exists = dst_set[id]; if (!exists) { dst_list.push_back(*it); dst_set.set(id); } } } // ITERATE }};/// Node list AND (set intersection)template<class TNode, class TSet, class TNodeList>class CTreeNodesAnd{public: void operator()(const TNodeList& src_nlist_a, const TNodeList& src_nlist_b, TNodeList& dst_nlist) { TSet tmp_set; this->operator()(src_nlist_a, src_nlist_b, dst_nlist, tmp_set); } void operator()(const TNodeList& src_nlist_a, const TNodeList& src_nlist_b, TNodeList& dst_nlist, TSet& dst_set) { TSet set_a; TreeListToSet(src_nlist_a, set_a.inserter()); {{ TSet set_b; TreeListToSet(src_nlist_b, set_b.inserter()); set_a &= set_b; }} CNodesToBitset<TNode, TSet, TNodeList> merge_func; merge_func.JoinNodeList(src_nlist_a, src_nlist_b, set_a, dst_nlist, dst_set); }}; /// Node list OR (set union)template<class TNode, class TSet, class TNodeList>class CTreeNodesOr{public: void operator()(const TNodeList& src_nlist_a, const TNodeList& src_nlist_b, TNodeList& dst_nlist) { TSet tmp_set; this->operator()(src_nlist_a, src_nlist_b, dst_nlist, tmp_set); } void operator()(const TNodeList& src_nlist_a, const TNodeList& src_nlist_b, TNodeList& dst_nlist, TSet& dst_set) { TSet set_a; TreeListToSet(src_nlist_a, set_a.inserter()); {{ TSet set_b; TreeListToSet(src_nlist_b, set_b.inserter()); set_a |= set_b; }} CNodesToBitset<TNode, TSet, TNodeList> merge_func; merge_func.JoinNodeList(src_nlist_a, src_nlist_b, set_a, dst_nlist, dst_set); }}; /* @} */END_NCBI_SCOPE/* * =========================================================================== * $Log: tree_algo.hpp,v $ * Revision 1000.2 2004/06/01 18:04:35 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7 * * Revision 1.7 2004/04/27 12:39:34 kuznets * Minimal set changed to work with ignore list of ids * * Revision 1.6 2004/04/22 17:58:07 kuznets * + more comments on minimal set * * Revision 1.5 2004/04/22 13:52:09 kuznets * + CTreeMinimalSet * * Revision 1.4 2004/04/21 16:42:18 kuznets * + AND, OR operations on node lists * * Revision 1.3 2004/04/21 13:27:18 kuznets * Bug fix: typename in templates * * Revision 1.2 2004/04/21 12:56:34 kuznets * Added tree related algorithms and utilities based on sets algebra * (TreeListToSet, TreeMakeParentsSet, TreeMakeSet, TreeSetToNodeList * CTreeNonRedundantSet) * * Revision 1.1 2004/04/19 16:02:06 kuznets * Initial revision. Migrated from <corelib/ncbi_tree.hpp> * * * ========================================================================== */#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?