tree_algo.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:25k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: tree_algo.hpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:04:35  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef ALGO___TREE__ALGO_HPP
  10. #define ALGO___TREE__ALGO_HPP
  11. /*  $Id: tree_algo.hpp,v 1000.2 2004/06/01 18:04:35 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author: Anatoliy Kuznetsov
  37.  *
  38.  * File Description:
  39.  *  Tree algorithms
  40.  *
  41.  */
  42. /// @file tree_algo.hpp
  43. /// Tree algorithms
  44. #include <corelib/ncbi_tree.hpp>
  45. BEGIN_NCBI_SCOPE
  46. /** @addtogroup Tree
  47.  *
  48.  * @{
  49.  */
  50. /////////////////////////////////////////////////////////////////////////////
  51. //
  52. //  General purpose tree algorithms
  53. //
  54. /// Visit every parent of the specified node
  55. /// 
  56. /// @param tree_node
  57. ///    Starting node
  58. /// @param func
  59. ///    Visiting functor
  60. /// @param skip_self
  61. ///    Flag to skip the first node (tree_node itself)
  62. ///    When TRUE visits only true ancestors
  63. template<class TTreeNode, class TFunc>
  64. TFunc TreeForEachParent(const TTreeNode& tree_node, 
  65.                         TFunc            func,
  66.                         bool             skip_self = false)
  67. {
  68.     const TTreeNode* node_ptr = &tree_node;
  69.     if (skip_self) {
  70.         node_ptr = node_ptr->GetParent();
  71.     }
  72.     for ( ;node_ptr; node_ptr = node_ptr->GetParent()) {
  73.         func(*node_ptr);
  74.     }
  75.     return func;
  76. }
  77. /// Functor to trace node pointers to root (TreeForEachParent)
  78. ///
  79. /// @internal
  80. /// @sa TreeForEachParent
  81. template<class TTreeNode, class TTraceContainer>
  82. class CTreeParentTraceFunc
  83. {
  84. public:
  85.     CTreeParentTraceFunc(TTraceContainer* trace) 
  86.      : m_Trace(trace)
  87.     {}
  88.     void operator()(const TTreeNode& node)
  89.     {
  90.         m_Trace->push_back(&node);
  91.     }
  92. private:
  93.     TTraceContainer* m_Trace;
  94. };
  95. /// Trace from the specified node to to the tree root
  96. ///
  97. /// Trace path is a container of node const node pointers 
  98. /// (The only requirement is push_back method)
  99. /// The input node becomes first element, then comes its parent.
  100. /// If the node is a tree top its pointer is the only element of the trace
  101. /// vector
  102. ///
  103. /// @param tree_node  
  104. ///    Starting node (added to the trace first)
  105. /// @param trace 
  106. ///    Trace container (vector<const TTreeNode*> or similar)
  107. ///
  108. template<class TTreeNode, class TTraceContainer>
  109. void TreeTraceToRoot(const TTreeNode& tree_node, TTraceContainer& trace)
  110. {
  111.     CTreeParentTraceFunc<TTreeNode, TTraceContainer> func(&trace);
  112.     TreeForEachParent(tree_node, func);
  113. }
  114. /// Change tree root (tree rotation)
  115. ///
  116. /// @param new_root_node
  117. ///    new node which becomes new tree root after the call
  118. template<class TTreeNode>
  119. void TreeReRoot(TTreeNode& new_root_node)
  120. {
  121.     vector<const TTreeNode*> trace;
  122.     TreeTraceToRoot(new_root_node, trace);
  123.     TTreeNode* local_root = &new_root_node;
  124.     ITERATE(typename vector<const TTreeNode*>, it, trace) {
  125.         TTreeNode* node = const_cast<TTreeNode*>(*it);
  126.         TTreeNode* parent = node->GetParent();
  127.         if (parent)
  128.             parent->DetachNode(node);
  129.         if (local_root != node)
  130.             local_root->AddNode(node);
  131.         local_root = node;
  132.     }
  133. }
  134. /// Check if two nodes have the same common root.
  135. ///
  136. /// Algorithm finds first common ancestor (farthest from the root)
  137. /// @param tree_node_a
  138. ///     Node A
  139. /// @param tree_node_b
  140. ///     Node B
  141. /// @return 
  142. ///     Nearest common root or NULL if there is no common parent
  143. ///
  144. template<class TTreeNode>
  145. const TTreeNode* TreeFindCommonParent(const TTreeNode& tree_node_a,
  146.                                       const TTreeNode& tree_node_b)
  147. {
  148.     typedef vector<const TTreeNode*>  TTraceVector;
  149.     TTraceVector trace_a;
  150.     TTraceVector trace_b;
  151.     TreeTraceToRoot(tree_node_a, trace_a);
  152.     TreeTraceToRoot(tree_node_b, trace_b);
  153.     // trace comparison: go to the 
  154.     const TTreeNode* node_candidate = 0;
  155.     // We need this next variables because of a bug(?) in MSVC 6 
  156.     //    vector::rbegin() returns non const reverse iterator 
  157.     //    for a non const vector (sort of)
  158.     const TTraceVector& ctr_a = trace_a;
  159.     const TTraceVector& ctr_b = trace_b;
  160.     typename TTraceVector::const_reverse_iterator it_a = ctr_a.rbegin();
  161.     typename TTraceVector::const_reverse_iterator it_b = ctr_b.rbegin();
  162.     typename TTraceVector::const_reverse_iterator it_a_end = ctr_a.rend();
  163.     typename TTraceVector::const_reverse_iterator it_b_end = ctr_b.rend();
  164.     
  165.     for (;it_a != it_a_end || it_b != it_b_end; ++it_a, ++it_b) {
  166.         const TTreeNode* node_a = *it_a;
  167.         const TTreeNode* node_b = *it_b;
  168.         if (node_a != node_b) {
  169.             break;
  170.         }
  171.         node_candidate = node_a;        
  172.     }
  173.     return node_candidate;
  174. }
  175. /// Tree print functor used as a tree traversal payload
  176. /// @internal
  177. template<class TTreeNode, class TConverter>
  178. class CTreePrintFunc
  179. {
  180. public:
  181.     CTreePrintFunc(CNcbiOstream& os, TConverter& conv, bool print_ptr)
  182.     : m_OStream(os),
  183.       m_Conv(conv),
  184.       m_Level(0),
  185.       m_PrintPtr(print_ptr)
  186.     {}
  187.     ETreeTraverseCode 
  188.     operator()(const TTreeNode& tr, int delta) 
  189.     {
  190.         m_Level += delta;
  191.         if (delta >= 0) { 
  192.             PrintLevelMargin();
  193.             const string& node_str = m_Conv(tr.GetValue());
  194.             if (m_PrintPtr) {
  195.                 m_OStream  
  196.                    << "[" << "0x" << hex << &tr << "]=> 0x" << tr.GetParent() 
  197.                    << " ( " << node_str << " ) " << endl;
  198.             } else {
  199.                 m_OStream << node_str << endl;
  200.             }
  201.         }
  202.         return eTreeTraverse;
  203.     }
  204.     void PrintLevelMargin()
  205.     {
  206.         for (int i = 0; i < m_Level; ++i) {
  207.             m_OStream << "  ";
  208.         }
  209.     }
  210.     
  211. private:
  212.     CNcbiOstream&  m_OStream;
  213.     TConverter&    m_Conv;
  214.     int            m_Level;
  215.     bool           m_PrintPtr;
  216. };
  217. /// Tree printing (use for debugging purposes)
  218. ///
  219. /// @param os
  220. ///     Stream to print the tree
  221. /// @param tree_node
  222. ///     Tree node to print (top or sub-tree)
  223. /// @param conv
  224. ///     Converter of node value to string (string Conv(node_value) )
  225. /// @param print_ptr
  226. ///     When TRUE function prints all internal pointers (debugging)
  227. ///
  228. template<class TTreeNode, class TConverter>
  229. void TreePrint(CNcbiOstream&     os, 
  230.                const TTreeNode&  tree_node, 
  231.                TConverter        conv,
  232.                bool              print_ptr = false)
  233. {
  234.     // fake const_cast, nothing to worry 
  235.     //   (should go away when we have const traverse)
  236.     TTreeNode* non_c_tr = const_cast<TTreeNode*>(&tree_node);
  237.     CTreePrintFunc<TTreeNode, TConverter> func(os, conv, print_ptr);
  238.     TreeDepthFirstTraverse(*non_c_tr, func);
  239. }
  240. /////////////////////////////////////////////////////////////////////////////
  241. //
  242. //  Algorithms for Id trees
  243. //
  244. /// Algorithm to to search for a node with specified id
  245. ///
  246. /// Tree is traversed back. When searching the upper(parent)
  247. /// level the algorithm never goes down the hierarchy but tries only 
  248. /// immediate children.
  249. ///
  250. template<class TPairTree, class TValue>
  251. const TPairTree* PairTreeBackTraceNode(const TPairTree& tr, 
  252.                                        const TValue&    search_id)
  253. {
  254.     const TPairTree* ptr = &tr;
  255.     do {
  256.         const typename TPairTree::TValueType& node_value = ptr->GetValue();
  257.         if (search_id == node_value) {
  258.             return (TPairTree*) ptr;
  259.         }
  260.         typename TPairTree::TNodeList_CI it = ptr->SubNodeBegin();
  261.         typename TPairTree::TNodeList_CI it_end = ptr->SubNodeEnd();
  262.         for (;it != it_end; ++it) {
  263.             const typename TPairTree::TParent* node = *it;
  264.             const typename TPairTree::TTreePair& node_pair = node->GetValue();
  265.             if (search_id == node_pair.GetId()) {
  266.                 return (TPairTree*) node;
  267.             }
  268.         } // for
  269.         ptr = (TPairTree*)ptr->GetParent();
  270.     } while (ptr);
  271.     return 0;
  272. }
  273. /// Algorithm to trace the pair tree and find specified leaf along the node path
  274. /// 
  275. /// Algorithm always chooses the deepest leaf 
  276. template<class TPairTree, class TPathList>
  277. const TPairTree* PairTreeTraceNode(const TPairTree& tr, const TPathList& node_path)
  278. {
  279.     _ASSERT(!node_path.empty());
  280.     const TPairTree* ptr = &tr;
  281.     const TPairTree* pfnd = 0;
  282.     typename TPathList::const_iterator last_it = node_path.end();
  283.     --last_it;
  284.     const typename TPathList::value_type& last_search_id = *last_it;
  285.     ITERATE(typename TPathList, sit, node_path) {
  286.         const typename TPairTree::TIdType& search_id = *sit;
  287.         bool sub_level_found = false;
  288.         
  289.         typename TPairTree::TNodeList_CI it = ptr->SubNodeBegin();
  290.         typename TPairTree::TNodeList_CI it_end = ptr->SubNodeEnd();
  291.         for (;it != it_end; ++it) {
  292.             const typename TPairTree::TParent* node = *it;
  293.             const typename TPairTree::TTreePair& node_pair = node->GetValue();
  294.             
  295.             if (node_pair.GetId() == search_id) {  
  296.                 ptr = (TPairTree*) node;
  297.                 sub_level_found = true;
  298.             }
  299.             if (node_pair.id == last_search_id) {
  300.                 pfnd = (TPairTree*) node;
  301.                 sub_level_found = true;
  302.             }
  303.             if (sub_level_found)
  304.                 break;
  305.         } // for it
  306.         if (!sub_level_found) {
  307.             break;
  308.         }
  309.         
  310.     } // ITERATE
  311.     return pfnd;
  312. }
  313. /// Convert list of node pointers to set of ids
  314. /// Input set is represented by input forward iterators
  315. /// Output set is a back insert iterator
  316. template<class TNodeListIt, class TBackInsert>
  317. void TreeListToSet(TNodeListIt node_list_first, 
  318.                    TNodeListIt node_list_last, 
  319.                    TBackInsert back_ins)
  320. {
  321.     for (;node_list_first != node_list_last; ++node_list_first)
  322.     {
  323.         unsigned uid = (unsigned)(*node_list_first)->GetValue().GetId();
  324.         *back_ins = uid;
  325.         ++back_ins;
  326.     }
  327. }
  328. /// Convert list of node pointers to set of ids
  329. /// @param node_list
  330. ///     node list container (must support const_iterator)
  331. /// @param back_ins
  332. ///     back insert iterator for the set container
  333. template<class TNodeList, class TBackInsert>
  334. void TreeListToSet(const TNodeList& node_list, TBackInsert back_ins)
  335. {
  336.     typename TNodeList::const_iterator it = node_list.begin();
  337.     typename TNodeList::const_iterator it_end = node_list.end();
  338.     TreeListToSet(it, it_end, back_ins);
  339. }
  340. /// Functor to trace node pointers to root and create set of parents 
  341. /// (TreeForEachParent)
  342. ///
  343. /// @internal
  344. /// @sa TreeForEachParent
  345. template<class TTreeNode, class TBackInsert>
  346. class CTreeIdToSetFunc
  347. {
  348. public:
  349.     CTreeIdToSetFunc(TBackInsert back_ins) 
  350.      : m_BackIns(back_ins)
  351.     {}
  352.     ETreeTraverseCode operator()(const TTreeNode& node, 
  353.                                  int              delta_level=0)
  354.     {
  355.         if (delta_level >= 0) {
  356.             *m_BackIns = node.GetValue().GetId();
  357.             ++m_BackIns;
  358.         }
  359.         return eTreeTraverse;
  360.     }
  361. private:
  362.     TBackInsert m_BackIns;
  363. };
  364. /// Traverses all ancestors and add their ids to a set
  365. ///
  366. /// @param tree_node
  367. ///   Starting node
  368. /// @param back_ins
  369. ///   Back insert iterator (represents set)
  370. ///
  371. template<class TNode, class TBackInsert>
  372. void TreeMakeParentsSet(const TNode& tree_node, TBackInsert back_ins)
  373. {
  374.     CTreeIdToSetFunc<TNode, TBackInsert> func(back_ins);
  375.     TreeForEachParent(tree_node, func, true /* only true parents */);
  376. }
  377. /// Create set of all sub-nodes (recursively)
  378. /// 
  379. /// @param tree_node
  380. ///    root node
  381. /// @param back_ins
  382. ///   Back insert iterator (represents set)
  383. ///
  384. template<class TNode, class TBackInsert>
  385. void TreeMakeSet(const TNode& tree_node, TBackInsert back_ins)
  386. {
  387.     TNode* node = const_cast<TNode*>(&tree_node);
  388.     CTreeIdToSetFunc<TNode, TBackInsert> func(back_ins);
  389.     TreeDepthFirstTraverse(*node, func);
  390. }
  391. /// Create set of all immediate sub-nodes (one level down from the root)
  392. /// 
  393. /// @param tree_node
  394. ///    root node
  395. /// @param back_ins
  396. ///   Back insert iterator (represents set)
  397. ///
  398. template<class TNode, class TBackInsert>
  399. void TreeMakeSubNodesSet(const TNode& tree_node, TBackInsert back_ins)
  400. {
  401.     typename TNode::TNodeList_CI it     = tree_node.SubNodeBegin();
  402.     typename TNode::TNodeList_CI it_end = tree_node.SubNodeEnd();
  403.     for(;it != it_end; ++it) {
  404.         const TNode* node = *it;
  405.         *back_ins = node->GetValue().GetId();
  406.         ++back_ins;
  407.     }
  408. }
  409. /// Functor to convert tree to a nodelist by the set pattern
  410. ///
  411. /// @internal
  412. template<class TTreeNode, class TSet, class TNodeList>
  413. class CTreeSet2NodeListFunc
  414. {
  415. public:
  416.     CTreeSet2NodeListFunc(const TSet& node_set, TNodeList* node_list)
  417.     : m_NodeSet(node_set),
  418.       m_NodeList(node_list)
  419.     {}
  420.     ETreeTraverseCode operator()(const TTreeNode& node, 
  421.                                  int              delta_level=0)
  422.     {
  423.         if (delta_level >= 0) {
  424.             unsigned id = node.GetValue().GetId();
  425.             bool b = m_NodeSet[id];
  426.             if (b) {
  427.                 m_NodeList->push_back(&node);
  428.             }
  429.         }
  430.         return eTreeTraverse;
  431.     }
  432. private:
  433.     const TSet&   m_NodeSet;
  434.     TNodeList*    m_NodeList;
  435. };
  436. /// Convert set of node ids to list of nodes
  437. ///
  438. /// Traverses the tree, if node is in the set adds node pointer to 
  439. /// the nodelist.
  440. ///
  441. template<class TNode, class TSet, class TNodeList>
  442. void TreeSetToNodeList(const TNode&  tree_node, 
  443.                        const TSet&   node_set, 
  444.                        TNodeList&    nlist)
  445. {
  446.     TNode* node = const_cast<TNode*>(&tree_node);
  447.     CTreeSet2NodeListFunc<TNode, TSet, TNodeList> func(node_set, &nlist);
  448.     TreeDepthFirstTraverse(node, func);
  449. }
  450. /// Class-algorithm to compute Non Redundant Set
  451. ///
  452. /// Takes a single nodelist as an arguiment and copies every node
  453. /// which has no ancestors in the source set. 
  454. /// @note Result set might be not minimal
  455. ///
  456. template<class TNode, class TSet, class TNodeList>
  457. class CTreeNonRedundantSet
  458. {
  459. public:
  460.     void operator()(const TNodeList& src_nlist,
  461.                     TNodeList&       dst_nlist)
  462.     {
  463.         TSet src_set;
  464.         TreeListToSet(src_nlist, src_set.inserter());
  465.         TSet ancestor_set;
  466.         ITERATE(typename TNodeList, it, src_nlist) {
  467.             TNode* snode = *it;
  468.             ancestor_set.clear();
  469.             TreeMakeParentsSet(*snode, ancestor_set.inserter());
  470.             ancestor_set &= src_set;
  471.             unsigned cnt = ancestor_set.count();
  472.             if (cnt == 0) { // source set contains no ancestors of the node
  473.                 // node is part of the non redundant set
  474.                 dst_nlist.push_back(snode);
  475.             }
  476.         } // ITERATE
  477.     }
  478. };
  479. /// Functor takes a single nodelist as an argument and tries to
  480. /// push that nodelist as high as it can. If all of the childred 
  481. /// of a given node are in the nodelist, the children are removed from 
  482. /// the nodelist and the parent is added. The process is repeated util
  483. /// it cannot be reduced anymore.
  484. ///
  485. template<class TNode, class TSet, class TNodeList>
  486. class CTreeMinimalSet
  487. {
  488. public:
  489.     /// Compute minimal set.
  490.     ///
  491.     /// @param src_nlist
  492.     ///    Source node list
  493.     /// @param dst_nlist
  494.     ///    Destination node list
  495.     /// @param ignore_set
  496.     ///    Set of node ids to ignore when we do reduction
  497.     ///
  498.     void operator()(const TNodeList& src_nlist,
  499.                     TNodeList&       dst_nlist,
  500.                     const TSet*      ignore_set = 0)
  501.     {
  502.         MinimalSet(src_nlist, dst_nlist, ignore_set);
  503.     }
  504. protected:
  505.     // The main workhorse function
  506.     void MinimalSet(const TNodeList& src_nlist,
  507.                     TNodeList&       dst_nlist,
  508.                     const TSet*      ignore_set = 0)
  509.     {
  510.         TSet src_set;
  511.         TreeListToSet(src_nlist, src_set.inserter());
  512.         TSet child_set;
  513.         TSet tmp_set;
  514.         bool moved_up; // flag that group of nodes got substituted for parent
  515.         do {
  516.             moved_up = 
  517.                 CheckNodeList(src_nlist, dst_nlist, 
  518.                               src_set,   tmp_set, child_set, ignore_set);
  519.             if (moved_up) {
  520.                 moved_up =
  521.                  CheckNodeList(dst_nlist, dst_nlist, 
  522.                                src_set,   tmp_set, child_set, ignore_set);
  523.             }
  524.         } while (moved_up); // repeat while we can move nodes up
  525.         loop_restart:
  526.         // clean the destination node list from reduced parents
  527.         NON_CONST_ITERATE(typename TNodeList, it, dst_nlist) {
  528.             TNode* snode = *it;
  529.             unsigned id = snode->GetValue().GetId();
  530.             // check if node was excluded from the source set
  531.             bool b = src_set[id];
  532.             if (!b) {
  533.                 dst_nlist.erase(it);
  534.                 goto loop_restart;
  535.             }
  536.         }
  537.         // add non reduced source nodes to the destination list
  538.         ITERATE(typename TNodeList, it, src_nlist) {
  539.             TNode* snode = *it;
  540.             unsigned id = snode->GetValue().GetId();
  541.             bool b = src_set[id];
  542.             if (b) {
  543.                 dst_nlist.push_back(snode);
  544.             }            
  545.         }
  546.     }
  547.     bool CheckNodeList(const TNodeList& nlist, 
  548.                        TNodeList&       dst_nlist,
  549.                        TSet&            src_set,
  550.                        TSet&            tmp_set,
  551.                        TSet&            child_set,
  552.                        const TSet*      ignore_set)
  553.     {
  554.         TNodeList  tmp_nlist; // (to avoid problems when &nlist == &dst_nlist)
  555.         bool promo_flag = false;
  556.         ITERATE(typename TNodeList, it, nlist) {
  557.             TNode* snode = *it;
  558.             unsigned id = snode->GetValue().GetId();
  559.             TNode* parent = snode->GetParent();
  560.             // check if node was excluded from the source set
  561.             bool b = src_set[id];
  562.             if (!b || (parent == 0)) 
  563.                 continue;
  564.             unsigned parent_id = parent->GetValue().GetId();
  565.             child_set.clear();
  566.             // Add immediate subnodes
  567.             TreeMakeSubNodesSet(*parent, child_set.inserter());
  568.             tmp_set = child_set;
  569.             tmp_set -= src_set;
  570.             if (ignore_set) {
  571.                 tmp_set -= *ignore_set;
  572.             }
  573.             if (tmp_set.none()) {  // we can move up to the parent
  574.                 // Add ALL subordinate node, not just children
  575.                 TreeMakeSet(*parent, child_set.inserter());
  576.                 src_set -= child_set;
  577.                 
  578.                 bool parent_in = src_set[parent_id];
  579.                 if (!parent_in) {
  580.                     src_set[parent_id] = true;
  581.                     //
  582.                     // precautionary measure: make sure we do not 
  583.                     // invalidate the source iterator 
  584.                     // (TNodeList can be a vector)
  585.                     //
  586.                     if (&nlist != &dst_nlist) {
  587.                         dst_nlist.push_back(parent);
  588.                     } else {
  589.                         tmp_nlist.push_back(parent);
  590.                     }
  591.                 }
  592.                 promo_flag = true;
  593.             }
  594.         } // ITERATE
  595.         // copy temp node list to the dst set
  596.         //
  597.         ITERATE(typename TNodeList, it, tmp_nlist) {
  598.             TNode* snode = *it;
  599.             dst_nlist.push_back(snode);
  600.         }
  601.         return promo_flag;
  602.     }
  603. };
  604. /// Utility to join to node lists according to a set of ids
  605. template<class TNode, class TSet, class TNodeList>
  606. class CNodesToBitset
  607. {
  608. public:
  609.     /// Join two node lists
  610.     ///
  611.     /// @param src_nlist_a
  612.     ///    node list 1
  613.     /// @param src_nlist_b
  614.     ///    node list 2
  615.     /// @param mask_set
  616.     ///    subset of two nodelists assigns nodes coming to dst_list
  617.     /// @param dst_list
  618.     ///    destination node list
  619.     /// @param dst_set
  620.     ///    auxiliary set used to track in target set
  621.     ///    (to make sure we will have non repeated list of nodes)
  622.     void JoinNodeList(const TNodeList&  src_nlist_a,
  623.                       const TNodeList&  src_nlist_b,
  624.                       const TSet&       mask_set,
  625.                       TNodeList&        dst_list,
  626.                       TSet&             dst_set)
  627.     {
  628.         dst_set.clear();
  629.         MaskCopyNodes(src_nlist_a, mask_set, dst_list, dst_set);
  630.         unsigned dst_count = dst_set.count();
  631.         unsigned src_count = mask_set.count();
  632.         if (src_count != dst_count) {
  633.             MaskCopyNodes(src_nlist_b, mask_set, dst_list, dst_set);
  634.         }
  635.     }
  636.     /// Copy nodes from the source node list to destination
  637.     /// if nodes are in the mask set and not yet in the destination set
  638.     void MaskCopyNodes(const TNodeList&  src_nlist,
  639.                        const TSet&       mask_set,
  640.                        TNodeList&        dst_list,
  641.                        TSet&             dst_set)
  642.     {
  643.         ITERATE(typename TNodeList, it, src_nlist) {
  644.             unsigned id = (*it)->GetValue().GetId();
  645.             bool exists = mask_set[id];
  646.             if (exists) {
  647.                 exists = dst_set[id];
  648.                 if (!exists) {
  649.                     dst_list.push_back(*it);
  650.                     dst_set.set(id);
  651.                 }
  652.             }
  653.         } // ITERATE
  654.     }
  655. };
  656. /// Node list AND (set intersection)
  657. template<class TNode, class TSet, class TNodeList>
  658. class CTreeNodesAnd
  659. {
  660. public:
  661.     void operator()(const TNodeList& src_nlist_a,
  662.                     const TNodeList& src_nlist_b,
  663.                     TNodeList&       dst_nlist)
  664.     {
  665.         TSet tmp_set;
  666.         this->operator()(src_nlist_a, src_nlist_b, dst_nlist, tmp_set);
  667.     }
  668.     void operator()(const TNodeList& src_nlist_a,
  669.                     const TNodeList& src_nlist_b,
  670.                     TNodeList&       dst_nlist,
  671.                     TSet&            dst_set)
  672.     {
  673.         TSet set_a;
  674.         TreeListToSet(src_nlist_a, set_a.inserter());
  675.         {{
  676.         TSet set_b;
  677.         TreeListToSet(src_nlist_b, set_b.inserter());        
  678.         set_a &= set_b;
  679.         }}
  680.         CNodesToBitset<TNode, TSet, TNodeList> merge_func;
  681.         merge_func.JoinNodeList(src_nlist_a, src_nlist_b, set_a, 
  682.                                 dst_nlist, dst_set);
  683.     }
  684. };         
  685. /// Node list OR (set union)
  686. template<class TNode, class TSet, class TNodeList>
  687. class CTreeNodesOr
  688. {
  689. public:
  690.     void operator()(const TNodeList& src_nlist_a,
  691.                     const TNodeList& src_nlist_b,
  692.                     TNodeList&       dst_nlist)
  693.     {
  694.         TSet tmp_set;
  695.         this->operator()(src_nlist_a, src_nlist_b, dst_nlist, tmp_set);
  696.     }
  697.     void operator()(const TNodeList& src_nlist_a,
  698.                     const TNodeList& src_nlist_b,
  699.                     TNodeList&       dst_nlist,
  700.                     TSet&            dst_set)
  701.     {
  702.         TSet set_a;
  703.         TreeListToSet(src_nlist_a, set_a.inserter());
  704.         {{
  705.         TSet set_b;
  706.         TreeListToSet(src_nlist_b, set_b.inserter());        
  707.         set_a |= set_b;
  708.         }}
  709.         CNodesToBitset<TNode, TSet, TNodeList> merge_func;
  710.         merge_func.JoinNodeList(src_nlist_a, src_nlist_b, set_a, 
  711.                                 dst_nlist, dst_set);
  712.     }
  713. };         
  714. /* @} */
  715. END_NCBI_SCOPE
  716. /*
  717.  * ===========================================================================
  718.  * $Log: tree_algo.hpp,v $
  719.  * Revision 1000.2  2004/06/01 18:04:35  gouriano
  720.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  721.  *
  722.  * Revision 1.7  2004/04/27 12:39:34  kuznets
  723.  * Minimal set changed to work with ignore list of ids
  724.  *
  725.  * Revision 1.6  2004/04/22 17:58:07  kuznets
  726.  * + more comments on minimal set
  727.  *
  728.  * Revision 1.5  2004/04/22 13:52:09  kuznets
  729.  * + CTreeMinimalSet
  730.  *
  731.  * Revision 1.4  2004/04/21 16:42:18  kuznets
  732.  * + AND, OR operations on node lists
  733.  *
  734.  * Revision 1.3  2004/04/21 13:27:18  kuznets
  735.  * Bug fix: typename in templates
  736.  *
  737.  * Revision 1.2  2004/04/21 12:56:34  kuznets
  738.  * Added tree related algorithms and utilities based on sets algebra
  739.  * (TreeListToSet, TreeMakeParentsSet, TreeMakeSet, TreeSetToNodeList
  740.  * CTreeNonRedundantSet)
  741.  *
  742.  * Revision 1.1  2004/04/19 16:02:06  kuznets
  743.  * Initial revision. Migrated from <corelib/ncbi_tree.hpp>
  744.  *
  745.  *
  746.  * ==========================================================================
  747.  */
  748. #endif