tree_algo.hpp

来自「ncbi源码」· HPP 代码 · 共 898 行 · 第 1/2 页

HPP
898
字号
/* * =========================================================================== * PRODUCTION $Log: tree_algo.hpp,v $ * PRODUCTION Revision 1000.2  2004/06/01 18:04:35  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7 * PRODUCTION * =========================================================================== */#ifndef ALGO___TREE__ALGO_HPP#define ALGO___TREE__ALGO_HPP/*  $Id: tree_algo.hpp,v 1000.2 2004/06/01 18:04:35 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 algorithms * *//// @file tree_algo.hpp/// Tree algorithms#include <corelib/ncbi_tree.hpp>BEGIN_NCBI_SCOPE/** @addtogroup Tree * * @{ *//////////////////////////////////////////////////////////////////////////////////  General purpose tree algorithms///// Visit every parent of the specified node/// /// @param tree_node///    Starting node/// @param func///    Visiting functor/// @param skip_self///    Flag to skip the first node (tree_node itself)///    When TRUE visits only true ancestorstemplate<class TTreeNode, class TFunc>TFunc TreeForEachParent(const TTreeNode& tree_node,                         TFunc            func,                        bool             skip_self = false){    const TTreeNode* node_ptr = &tree_node;    if (skip_self) {        node_ptr = node_ptr->GetParent();    }    for ( ;node_ptr; node_ptr = node_ptr->GetParent()) {        func(*node_ptr);    }    return func;}/// Functor to trace node pointers to root (TreeForEachParent)////// @internal/// @sa TreeForEachParenttemplate<class TTreeNode, class TTraceContainer>class CTreeParentTraceFunc{public:    CTreeParentTraceFunc(TTraceContainer* trace)      : m_Trace(trace)    {}    void operator()(const TTreeNode& node)    {        m_Trace->push_back(&node);    }private:    TTraceContainer* m_Trace;};/// Trace from the specified node to to the tree root////// Trace path is a container of node const node pointers /// (The only requirement is push_back method)/// The input node becomes first element, then comes its parent./// If the node is a tree top its pointer is the only element of the trace/// vector////// @param tree_node  ///    Starting node (added to the trace first)/// @param trace ///    Trace container (vector<const TTreeNode*> or similar)///template<class TTreeNode, class TTraceContainer>void TreeTraceToRoot(const TTreeNode& tree_node, TTraceContainer& trace){    CTreeParentTraceFunc<TTreeNode, TTraceContainer> func(&trace);    TreeForEachParent(tree_node, func);}/// Change tree root (tree rotation)////// @param new_root_node///    new node which becomes new tree root after the calltemplate<class TTreeNode>void TreeReRoot(TTreeNode& new_root_node){    vector<const TTreeNode*> trace;    TreeTraceToRoot(new_root_node, trace);    TTreeNode* local_root = &new_root_node;    ITERATE(typename vector<const TTreeNode*>, it, trace) {        TTreeNode* node = const_cast<TTreeNode*>(*it);        TTreeNode* parent = node->GetParent();        if (parent)            parent->DetachNode(node);        if (local_root != node)            local_root->AddNode(node);        local_root = node;    }}/// Check if two nodes have the same common root.////// Algorithm finds first common ancestor (farthest from the root)/// @param tree_node_a///     Node A/// @param tree_node_b///     Node B/// @return ///     Nearest common root or NULL if there is no common parent///template<class TTreeNode>const TTreeNode* TreeFindCommonParent(const TTreeNode& tree_node_a,                                      const TTreeNode& tree_node_b){    typedef vector<const TTreeNode*>  TTraceVector;    TTraceVector trace_a;    TTraceVector trace_b;    TreeTraceToRoot(tree_node_a, trace_a);    TreeTraceToRoot(tree_node_b, trace_b);    // trace comparison: go to the     const TTreeNode* node_candidate = 0;    // We need this next variables because of a bug(?) in MSVC 6     //    vector::rbegin() returns non const reverse iterator     //    for a non const vector (sort of)    const TTraceVector& ctr_a = trace_a;    const TTraceVector& ctr_b = trace_b;    typename TTraceVector::const_reverse_iterator it_a = ctr_a.rbegin();    typename TTraceVector::const_reverse_iterator it_b = ctr_b.rbegin();    typename TTraceVector::const_reverse_iterator it_a_end = ctr_a.rend();    typename TTraceVector::const_reverse_iterator it_b_end = ctr_b.rend();        for (;it_a != it_a_end || it_b != it_b_end; ++it_a, ++it_b) {        const TTreeNode* node_a = *it_a;        const TTreeNode* node_b = *it_b;        if (node_a != node_b) {            break;        }        node_candidate = node_a;            }    return node_candidate;}/// Tree print functor used as a tree traversal payload/// @internaltemplate<class TTreeNode, class TConverter>class CTreePrintFunc{public:    CTreePrintFunc(CNcbiOstream& os, TConverter& conv, bool print_ptr)    : m_OStream(os),      m_Conv(conv),      m_Level(0),      m_PrintPtr(print_ptr)    {}    ETreeTraverseCode     operator()(const TTreeNode& tr, int delta)     {        m_Level += delta;        if (delta >= 0) {             PrintLevelMargin();            const string& node_str = m_Conv(tr.GetValue());            if (m_PrintPtr) {                m_OStream                     << "[" << "0x" << hex << &tr << "]=> 0x" << tr.GetParent()                    << " ( " << node_str << " ) " << endl;            } else {                m_OStream << node_str << endl;            }        }        return eTreeTraverse;    }    void PrintLevelMargin()    {        for (int i = 0; i < m_Level; ++i) {            m_OStream << "  ";        }    }    private:    CNcbiOstream&  m_OStream;    TConverter&    m_Conv;    int            m_Level;    bool           m_PrintPtr;};/// Tree printing (use for debugging purposes)////// @param os///     Stream to print the tree/// @param tree_node///     Tree node to print (top or sub-tree)/// @param conv///     Converter of node value to string (string Conv(node_value) )/// @param print_ptr///     When TRUE function prints all internal pointers (debugging)///template<class TTreeNode, class TConverter>void TreePrint(CNcbiOstream&     os,                const TTreeNode&  tree_node,                TConverter        conv,               bool              print_ptr = false){    // fake const_cast, nothing to worry     //   (should go away when we have const traverse)    TTreeNode* non_c_tr = const_cast<TTreeNode*>(&tree_node);    CTreePrintFunc<TTreeNode, TConverter> func(os, conv, print_ptr);    TreeDepthFirstTraverse(*non_c_tr, func);}/////////////////////////////////////////////////////////////////////////////////  Algorithms for Id trees///// Algorithm to to search for a node with specified id////// Tree is traversed back. When searching the upper(parent)/// level the algorithm never goes down the hierarchy but tries only /// immediate children.///template<class TPairTree, class TValue>const TPairTree* PairTreeBackTraceNode(const TPairTree& tr,                                        const TValue&    search_id){    const TPairTree* ptr = &tr;    do {        const typename TPairTree::TValueType& node_value = ptr->GetValue();        if (search_id == node_value) {            return (TPairTree*) ptr;        }        typename TPairTree::TNodeList_CI it = ptr->SubNodeBegin();        typename TPairTree::TNodeList_CI it_end = ptr->SubNodeEnd();        for (;it != it_end; ++it) {            const typename TPairTree::TParent* node = *it;            const typename TPairTree::TTreePair& node_pair = node->GetValue();            if (search_id == node_pair.GetId()) {                return (TPairTree*) node;            }        } // for        ptr = (TPairTree*)ptr->GetParent();    } while (ptr);    return 0;}/// Algorithm to trace the pair tree and find specified leaf along the node path/// /// Algorithm always chooses the deepest leaf template<class TPairTree, class TPathList>const TPairTree* PairTreeTraceNode(const TPairTree& tr, const TPathList& node_path){    _ASSERT(!node_path.empty());    const TPairTree* ptr = &tr;    const TPairTree* pfnd = 0;    typename TPathList::const_iterator last_it = node_path.end();    --last_it;    const typename TPathList::value_type& last_search_id = *last_it;    ITERATE(typename TPathList, sit, node_path) {        const typename TPairTree::TIdType& search_id = *sit;        bool sub_level_found = false;                typename TPairTree::TNodeList_CI it = ptr->SubNodeBegin();        typename TPairTree::TNodeList_CI it_end = ptr->SubNodeEnd();        for (;it != it_end; ++it) {            const typename TPairTree::TParent* node = *it;            const typename TPairTree::TTreePair& node_pair = node->GetValue();                        if (node_pair.GetId() == search_id) {                  ptr = (TPairTree*) node;                sub_level_found = true;            }            if (node_pair.id == last_search_id) {                pfnd = (TPairTree*) node;                sub_level_found = true;            }            if (sub_level_found)                break;        } // for it        if (!sub_level_found) {            break;        }            } // ITERATE    return pfnd;}/// Convert list of node pointers to set of ids/// Input set is represented by input forward iterators/// Output set is a back insert iteratortemplate<class TNodeListIt, class TBackInsert>void TreeListToSet(TNodeListIt node_list_first,                    TNodeListIt node_list_last,                    TBackInsert back_ins){    for (;node_list_first != node_list_last; ++node_list_first)    {        unsigned uid = (unsigned)(*node_list_first)->GetValue().GetId();        *back_ins = uid;        ++back_ins;    }}/// Convert list of node pointers to set of ids/// @param node_list///     node list container (must support const_iterator)/// @param back_ins///     back insert iterator for the set containertemplate<class TNodeList, class TBackInsert>void TreeListToSet(const TNodeList& node_list, TBackInsert back_ins){    typename TNodeList::const_iterator it = node_list.begin();    typename TNodeList::const_iterator it_end = node_list.end();    TreeListToSet(it, it_end, back_ins);}/// Functor to trace node pointers to root and create set of parents /// (TreeForEachParent)////// @internal/// @sa TreeForEachParenttemplate<class TTreeNode, class TBackInsert>class CTreeIdToSetFunc{public:    CTreeIdToSetFunc(TBackInsert back_ins)      : m_BackIns(back_ins)    {}    ETreeTraverseCode operator()(const TTreeNode& node,                                  int              delta_level=0)    {        if (delta_level >= 0) {            *m_BackIns = node.GetValue().GetId();            ++m_BackIns;        }        return eTreeTraverse;    }private:    TBackInsert m_BackIns;};/// Traverses all ancestors and add their ids to a set////// @param tree_node///   Starting node/// @param back_ins///   Back insert iterator (represents set)///template<class TNode, class TBackInsert>void TreeMakeParentsSet(const TNode& tree_node, TBackInsert back_ins){    CTreeIdToSetFunc<TNode, TBackInsert> func(back_ins);    TreeForEachParent(tree_node, func, true /* only true parents */);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?