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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: itree.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:40:11  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: itree.cpp,v 1000.1 2004/06/01 19:40:11 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Implementation of interval search tree.
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <util/itree.hpp>
  44. BEGIN_NCBI_SCOPE
  45. inline
  46. CIntervalTree::coordinate_type CIntervalTree::GetMaxRootCoordinate(void) const
  47. {
  48.     coordinate_type max = m_Root.m_Key * 2;
  49.     if ( max <= 0 )
  50.         max = TTraits::GetMaxCoordinate();
  51.     return max;
  52. }
  53. inline
  54. CIntervalTree::coordinate_type CIntervalTree::GetNextRootKey(void) const
  55. {
  56.     coordinate_type nextKey = m_Root.m_Key * 2;
  57.     _ASSERT(nextKey > 0);
  58.     return nextKey;
  59. }
  60. void CIntervalTree::DoInsert(const interval_type& interval, TTreeMapI value)
  61. {
  62.     _ASSERT(TTraits::IsNormal(interval));
  63.     // ensure our tree covers specified interval
  64.     if ( interval.GetTo() > GetMaxRootCoordinate() ) {
  65.         // insert one more level on top
  66.         if ( m_Root.m_Left || m_Root.m_Right || m_Root.m_NodeIntervals ) {
  67.             // non empty tree, insert new root node
  68.             do {
  69.                 TTreeNode* newLeft = AllocNode();
  70.                 // copy root node contents
  71.                 *newLeft = m_Root;
  72.                 // fill new root
  73.                 m_Root.m_Key = GetNextRootKey();
  74.                 m_Root.m_Left = newLeft;
  75.                 m_Root.m_Right = 0;
  76.                 m_Root.m_NodeIntervals = 0;
  77.             } while ( interval.GetTo() > GetMaxRootCoordinate() );
  78.         }
  79.         else {
  80.             // empty tree, just recalculate root
  81.             do {
  82.                 m_Root.m_Key = GetNextRootKey();
  83.             } while ( interval.GetTo() > GetMaxRootCoordinate() );
  84.         }
  85.     }
  86.     TTreeNode* node = &m_Root;
  87.     coordinate_type nodeSize = m_Root.m_Key;
  88.     for ( ;; ) {
  89.         coordinate_type key = node->m_Key;
  90.         nodeSize = (nodeSize + 1) / 2;
  91.         TTreeNode** nextPtr;
  92.         coordinate_type nextKeyOffset;
  93.         if ( interval.GetFrom() > key  ) {
  94.             nextPtr = &node->m_Right;
  95.             nextKeyOffset = nodeSize;
  96.         }
  97.         else if ( interval.GetTo() < key ) {
  98.             nextPtr = &node->m_Left;
  99.             nextKeyOffset = -nodeSize;
  100.         }
  101.         else {
  102.             // found our tile
  103.             TTreeNodeInts* nodeIntervals = node->m_NodeIntervals;
  104.             if ( !nodeIntervals )
  105.                 node->m_NodeIntervals = nodeIntervals = CreateNodeIntervals();
  106.             nodeIntervals->Insert(interval, value);
  107.             return;
  108.         }
  109.         TTreeNode* next = *nextPtr;
  110.         if ( !next ) // create new node
  111.             (*nextPtr) = next = InitNode(AllocNode(), key + nextKeyOffset);
  112.         _ASSERT(next->m_Key == key + nextKeyOffset);
  113.         node = next;
  114.     }
  115. }
  116. bool CIntervalTree::DoDelete(TTreeNode* node, const interval_type& interval,
  117.                              TTreeMapI value)
  118. {
  119.     _ASSERT(node);
  120.     coordinate_type key = node->m_Key;
  121.     if ( interval.GetFrom() > key ) {
  122.         // left
  123.         return DoDelete(node->m_Right, interval, value) &&
  124.             !node->m_NodeIntervals && !node->m_Left;
  125.     }
  126.     else if ( interval.GetTo() < key ) {
  127.         // right
  128.         return DoDelete(node->m_Left, interval, value) &&
  129.             !node->m_NodeIntervals && !node->m_Right;
  130.     }
  131.     else {
  132.         // inside
  133.         TTreeNodeInts* nodeIntervals = node->m_NodeIntervals;
  134.         _ASSERT(nodeIntervals);
  135.         if ( !nodeIntervals->Delete(interval, value) )
  136.             return false; // node intervals non empty
  137.         // remove node intervals
  138.         DeleteNodeIntervals(nodeIntervals);
  139.         node->m_NodeIntervals = 0;
  140.         // delete node if it doesn't have leaves
  141.         return !node->m_Left && !node->m_Right;
  142.     }
  143. }
  144. void CIntervalTree::Destroy(void)
  145. {
  146.     ClearNode(&m_Root);
  147.     m_ByX.clear();
  148. }
  149. CIntervalTree::iterator CIntervalTree::Insert(const interval_type& interval,
  150.                                               const mapped_type& value)
  151. {
  152.     TTreeMapI iter = m_ByX.insert(TTreeMapValue(interval.GetFrom(),
  153.                                                 interval.GetTo(),
  154.                                                 value));
  155.     DoInsert(interval, iter);
  156.     return iterator(0, TTraits::GetMaxCoordinate(), &TTreeMap::get(iter));
  157. }
  158. CIntervalTree::const_iterator
  159. CIntervalTree::IntervalsOverlapping(const interval_type& interval) const
  160. {
  161.     coordinate_type x = interval.GetFrom();
  162.     coordinate_type y = interval.GetTo();
  163.     const_iterator it(x, TTraits::GetMaxCoordinate(), 0, &m_Root);
  164.     TTreeMapCI iter =
  165.         m_ByX.lower_bound(TTreeMapValue(x + 1, 0, mapped_type()));
  166.     if ( iter != m_ByX.end() && iter->GetKey() <= y ) {
  167.         it.m_SearchLimit = y;
  168.         it.m_CurrentMapValue = &*iter;
  169.     }
  170.     else {
  171.         it.NextLevel();
  172.     }
  173.     return it;
  174. }
  175. CIntervalTree::iterator
  176. CIntervalTree::IntervalsOverlapping(const interval_type& interval)
  177. {
  178.     coordinate_type x = interval.GetFrom();
  179.     coordinate_type y = interval.GetTo();
  180.     iterator it(x, TTraits::GetMaxCoordinate(), 0, &m_Root);
  181.     TTreeMapI iter =
  182.         m_ByX.lower_bound(TTreeMapValue(x + 1, 0, mapped_type()));
  183.     if ( iter != m_ByX.end() && iter->GetKey() <= y ) {
  184.         it.m_SearchLimit = y;
  185.         it.m_CurrentMapValue = &TTreeMap::get(iter);
  186.     }
  187.     else {
  188.         it.NextLevel();
  189.     }
  190.     return it;
  191. }
  192. CIntervalTree::TTreeNode* CIntervalTree::AllocNode(void)
  193. {
  194.     return m_NodeAllocator.allocate(1, (TTreeNode*) 0);
  195. }
  196. void CIntervalTree::DeallocNode(TTreeNode* node)
  197. {
  198.     m_NodeAllocator.deallocate(node, 1);
  199. }
  200. CIntervalTree::TTreeNodeInts* CIntervalTree::AllocNodeIntervals(void)
  201. {
  202.     return m_NodeIntervalsAllocator.allocate(1, (TTreeNodeInts*) 0);
  203. }
  204. void CIntervalTree::DeallocNodeIntervals(TTreeNodeInts* ptr)
  205. {
  206.     m_NodeIntervalsAllocator.deallocate(ptr, 1);
  207. }
  208. CIntervalTree::TTreeNodeInts* CIntervalTree::CreateNodeIntervals(void)
  209. {
  210.     TTreeNodeInts* ints = new (AllocNodeIntervals())TTreeNodeInts();
  211. #if defined(_RWSTD_VER) && !defined(_RWSTD_STRICT_ANSI)
  212.     ints->m_ByX.allocation_size(16);
  213.     ints->m_ByY.allocation_size(16);
  214. #endif
  215.     return ints;
  216. }
  217. void CIntervalTree::DeleteNodeIntervals(TTreeNodeInts* ptr)
  218. {
  219.     if ( ptr ) {
  220.         ptr->~TTreeNodeInts();
  221.         DeallocNodeIntervals(ptr);
  222.     }
  223. }
  224. void CIntervalTree::ClearNode(TTreeNode* node)
  225. {
  226.     DeleteNodeIntervals(node->m_NodeIntervals);
  227.     DeleteNode(node->m_Left);
  228.     DeleteNode(node->m_Right);
  229.     node->m_Left = node->m_Right = 0;
  230. }
  231. pair<double, CIntervalTree::size_type> CIntervalTree::Stat(void) const
  232. {
  233.     SStat stat;
  234.     stat.total = stat.count = stat.max = 0;
  235.     Stat(&m_Root, stat);
  236.     return make_pair(double(stat.total) / stat.count, stat.max);
  237. }
  238. void CIntervalTree::Stat(const TTreeNode* node, SStat& stat) const
  239. {
  240.     if ( !node )
  241.         return;
  242.     if ( node->m_NodeIntervals ) {
  243.         size_type len = node->m_NodeIntervals->m_ByX.size();
  244.         ++stat.count;
  245.         stat.total += len;
  246.         stat.max = max(stat.max, len);
  247.     }
  248.     Stat(node->m_Right, stat);
  249.     Stat(node->m_Left, stat);
  250. }
  251. /*
  252. * ---------------------------------------------------------------------------
  253. * $Log: itree.cpp,v $
  254. * Revision 1000.1  2004/06/01 19:40:11  gouriano
  255. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  256. *
  257. * Revision 1.7  2004/05/17 21:06:02  gorelenk
  258. * Added include of PCH ncbi_pch.hpp
  259. *
  260. * Revision 1.6  2003/02/07 16:54:02  vasilche
  261. * Pass all structures with size > sizeof int by reference.
  262. * Move cvs log to the end of files.
  263. *
  264. * Revision 1.5  2001/05/30 15:59:28  vakatov
  265. * CIntervalTree::AllocNode[Intervals]() -- explicit cast of "0" to
  266. * make the ICC compiler understand what's going on
  267. *
  268. * Revision 1.4  2001/01/29 15:18:46  vasilche
  269. * Cleaned CRangeMap and CIntervalTree classes.
  270. *
  271. * Revision 1.3  2001/01/11 15:16:28  vasilche
  272. * On MSVC second argument of allocator::allocate() is not optional.
  273. *
  274. * Revision 1.2  2001/01/11 15:08:20  vasilche
  275. * Removed missing header.
  276. *
  277. * Revision 1.1  2001/01/11 15:00:44  vasilche
  278. * Added CIntervalTree for seraching on set of intervals.
  279. *
  280. * ===========================================================================
  281. */
  282. END_NCBI_SCOPE